diff options
author | Mike Pagano <mpagano@gentoo.org> | 2024-03-01 08:06:04 -0500 |
---|---|---|
committer | Mike Pagano <mpagano@gentoo.org> | 2024-03-01 08:06:04 -0500 |
commit | b0ddef42428ee2b183e51e4db4fdc18dad61fbd9 (patch) | |
tree | 8a84597612c39daebb5363dfba00542c138f9909 | |
parent | Add the BMQ(BitMap Queue) Scheduler (diff) | |
download | linux-patches-b0ddef42428ee2b183e51e4db4fdc18dad61fbd9.tar.gz linux-patches-b0ddef42428ee2b183e51e4db4fdc18dad61fbd9.tar.bz2 linux-patches-b0ddef42428ee2b183e51e4db4fdc18dad61fbd9.zip |
Linux patch 6.7.76.7-11
Signed-off-by: Mike Pagano <mpagano@gentoo.org>
-rw-r--r-- | 0000_README | 4 | ||||
-rw-r--r-- | 1006_linux-6.7.7.patch | 14267 |
2 files changed, 14271 insertions, 0 deletions
diff --git a/0000_README b/0000_README index b343fd35..178ef64f 100644 --- a/0000_README +++ b/0000_README @@ -67,6 +67,10 @@ Patch: 1005_linux-6.7.6.patch From: https://www.kernel.org Desc: Linux 6.7.6 +Patch: 1006_linux-6.7.7.patch +From: https://www.kernel.org +Desc: Linux 6.7.7 + Patch: 1510_fs-enable-link-security-restrictions-by-default.patch From: http://sources.debian.net/src/linux/3.16.7-ckt4-3/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch/ Desc: Enable link security restrictions by default. diff --git a/1006_linux-6.7.7.patch b/1006_linux-6.7.7.patch new file mode 100644 index 00000000..97237e43 --- /dev/null +++ b/1006_linux-6.7.7.patch @@ -0,0 +1,14267 @@ +diff --git a/Documentation/conf.py b/Documentation/conf.py +index d4fdf6a3875a8..dfc19c915d5c4 100644 +--- a/Documentation/conf.py ++++ b/Documentation/conf.py +@@ -383,6 +383,12 @@ latex_elements = { + verbatimhintsturnover=false, + ''', + ++ # ++ # Some of our authors are fond of deep nesting; tell latex to ++ # cope. ++ # ++ 'maxlistdepth': '10', ++ + # For CJK One-half spacing, need to be in front of hyperref + 'extrapackages': r'\usepackage{setspace}', + +diff --git a/Documentation/dev-tools/kunit/usage.rst b/Documentation/dev-tools/kunit/usage.rst +index c27e1646ecd9c..9db12e91668e3 100644 +--- a/Documentation/dev-tools/kunit/usage.rst ++++ b/Documentation/dev-tools/kunit/usage.rst +@@ -651,12 +651,16 @@ For example: + } + + Note that, for functions like device_unregister which only accept a single +-pointer-sized argument, it's possible to directly cast that function to +-a ``kunit_action_t`` rather than writing a wrapper function, for example: ++pointer-sized argument, it's possible to automatically generate a wrapper ++with the ``KUNIT_DEFINE_ACTION_WRAPPER()`` macro, for example: + + .. code-block:: C + +- kunit_add_action(test, (kunit_action_t *)&device_unregister, &dev); ++ KUNIT_DEFINE_ACTION_WRAPPER(device_unregister, device_unregister_wrapper, struct device *); ++ kunit_add_action(test, &device_unregister_wrapper, &dev); ++ ++You should do this in preference to manually casting to the ``kunit_action_t`` type, ++as casting function pointers will break Control Flow Integrity (CFI). + + ``kunit_add_action`` can fail if, for example, the system is out of memory. + You can use ``kunit_add_action_or_reset`` instead which runs the action +diff --git a/Makefile b/Makefile +index d07a8e0179acf..72ee3609aae34 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 7 +-SUBLEVEL = 6 ++SUBLEVEL = 7 + EXTRAVERSION = + NAME = Hurr durr I'ma ninja sloth + +diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-bletchley.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-bletchley.dts +index e899de681f475..5be0e8fd2633c 100644 +--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-bletchley.dts ++++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-bletchley.dts +@@ -45,8 +45,8 @@ spi1_gpio: spi1-gpio { + num-chipselects = <1>; + cs-gpios = <&gpio0 ASPEED_GPIO(Z, 0) GPIO_ACTIVE_LOW>; + +- tpmdev@0 { +- compatible = "tcg,tpm_tis-spi"; ++ tpm@0 { ++ compatible = "infineon,slb9670", "tcg,tpm_tis-spi"; + spi-max-frequency = <33000000>; + reg = <0>; + }; +diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-wedge400.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-wedge400.dts +index a677c827e758f..5a8169bbda879 100644 +--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-wedge400.dts ++++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-wedge400.dts +@@ -80,8 +80,8 @@ spi_gpio: spi { + gpio-miso = <&gpio ASPEED_GPIO(R, 5) GPIO_ACTIVE_HIGH>; + num-chipselects = <1>; + +- tpmdev@0 { +- compatible = "tcg,tpm_tis-spi"; ++ tpm@0 { ++ compatible = "infineon,slb9670", "tcg,tpm_tis-spi"; + spi-max-frequency = <33000000>; + reg = <0>; + }; +diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-tacoma.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-tacoma.dts +index 3f6010ef2b86f..213023bc5aec4 100644 +--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-tacoma.dts ++++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-tacoma.dts +@@ -456,7 +456,7 @@ &i2c1 { + status = "okay"; + + tpm: tpm@2e { +- compatible = "tcg,tpm-tis-i2c"; ++ compatible = "nuvoton,npct75x", "tcg,tpm-tis-i2c"; + reg = <0x2e>; + }; + }; +diff --git a/arch/arm/boot/dts/aspeed/ast2600-facebook-netbmc-common.dtsi b/arch/arm/boot/dts/aspeed/ast2600-facebook-netbmc-common.dtsi +index 31590d3186a2e..00e5887c926f1 100644 +--- a/arch/arm/boot/dts/aspeed/ast2600-facebook-netbmc-common.dtsi ++++ b/arch/arm/boot/dts/aspeed/ast2600-facebook-netbmc-common.dtsi +@@ -35,8 +35,8 @@ spi_gpio: spi { + gpio-mosi = <&gpio0 ASPEED_GPIO(X, 4) GPIO_ACTIVE_HIGH>; + gpio-miso = <&gpio0 ASPEED_GPIO(X, 5) GPIO_ACTIVE_HIGH>; + +- tpmdev@0 { +- compatible = "tcg,tpm_tis-spi"; ++ tpm@0 { ++ compatible = "infineon,slb9670", "tcg,tpm_tis-spi"; + spi-max-frequency = <33000000>; + reg = <0>; + }; +diff --git a/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri.dtsi +index 44cc4ff1d0df3..d12fb44aeb140 100644 +--- a/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri.dtsi ++++ b/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri.dtsi +@@ -116,7 +116,7 @@ &ecspi1 { + tpm_tis: tpm@1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_tpm>; +- compatible = "tcg,tpm_tis-spi"; ++ compatible = "infineon,slb9670", "tcg,tpm_tis-spi"; + reg = <1>; + spi-max-frequency = <20000000>; + interrupt-parent = <&gpio5>; +diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-flex-concentrator.dts b/arch/arm/boot/dts/nxp/imx/imx7d-flex-concentrator.dts +index 3a723843d5626..9984b343cdf0c 100644 +--- a/arch/arm/boot/dts/nxp/imx/imx7d-flex-concentrator.dts ++++ b/arch/arm/boot/dts/nxp/imx/imx7d-flex-concentrator.dts +@@ -130,7 +130,7 @@ &ecspi4 { + * TCG specification - Section 6.4.1 Clocking: + * TPM shall support a SPI clock frequency range of 10-24 MHz. + */ +- st33htph: tpm-tis@0 { ++ st33htph: tpm@0 { + compatible = "st,st33htpm-spi", "tcg,tpm_tis-spi"; + reg = <0>; + spi-max-frequency = <24000000>; +diff --git a/arch/arm/boot/dts/ti/omap/am335x-moxa-uc-2100-common.dtsi b/arch/arm/boot/dts/ti/omap/am335x-moxa-uc-2100-common.dtsi +index b8730aa52ce6f..a59331aa58e55 100644 +--- a/arch/arm/boot/dts/ti/omap/am335x-moxa-uc-2100-common.dtsi ++++ b/arch/arm/boot/dts/ti/omap/am335x-moxa-uc-2100-common.dtsi +@@ -217,7 +217,7 @@ &spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spi1_pins>; + +- tpm_spi_tis@0 { ++ tpm@0 { + compatible = "tcg,tpm_tis-spi"; + reg = <0>; + spi-max-frequency = <500000>; +diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c +index 71b1139764204..8b1ec60a9a467 100644 +--- a/arch/arm/mach-ep93xx/core.c ++++ b/arch/arm/mach-ep93xx/core.c +@@ -339,6 +339,7 @@ static struct gpiod_lookup_table ep93xx_i2c_gpiod_table = { + GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN), + GPIO_LOOKUP_IDX("G", 0, NULL, 1, + GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN), ++ { } + }, + }; + +diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts +index d98a040860a48..5828c9d7821de 100644 +--- a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts ++++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts +@@ -486,7 +486,7 @@ &uart3 { /* A53 Debug */ + &uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart4>; +- status = "okay"; ++ status = "disabled"; + }; + + &usb3_phy0 { +diff --git a/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts b/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts +index 4240e20d38ac3..258e90cc16ff3 100644 +--- a/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts ++++ b/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts +@@ -168,6 +168,13 @@ reg_vcc_12v0: regulator-12v0 { + enable-active-high; + }; + ++ reg_vcc_1v8: regulator-1v8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCC_1V8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ }; ++ + reg_vcc_3v3: regulator-3v3 { + compatible = "regulator-fixed"; + regulator-name = "VCC_3V3"; +@@ -464,7 +471,7 @@ tlv320aic3x04: audio-codec@18 { + clock-names = "mclk"; + clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI3_MCLK1>; + reset-gpios = <&gpio4 29 GPIO_ACTIVE_LOW>; +- iov-supply = <®_vcc_3v3>; ++ iov-supply = <®_vcc_1v8>; + ldoin-supply = <®_vcc_3v3>; + }; + +diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi +index 42ce78beb4134..20955556b624d 100644 +--- a/arch/arm64/boot/dts/rockchip/px30.dtsi ++++ b/arch/arm64/boot/dts/rockchip/px30.dtsi +@@ -632,6 +632,7 @@ spi0: spi@ff1d0000 { + clock-names = "spiclk", "apb_pclk"; + dmas = <&dmac 12>, <&dmac 13>; + dma-names = "tx", "rx"; ++ num-cs = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&spi0_clk &spi0_csn &spi0_miso &spi0_mosi>; + #address-cells = <1>; +@@ -647,6 +648,7 @@ spi1: spi@ff1d8000 { + clock-names = "spiclk", "apb_pclk"; + dmas = <&dmac 14>, <&dmac 15>; + dma-names = "tx", "rx"; ++ num-cs = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&spi1_clk &spi1_csn0 &spi1_csn1 &spi1_miso &spi1_mosi>; + #address-cells = <1>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts b/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts +index 60f00ceb630e1..3b675fd0c5ea5 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts +@@ -196,13 +196,13 @@ &gpio0 { + + &gpio1 { + gpio-line-names = /* GPIO1 A0-A7 */ +- "HEADER_27_3v3", "HEADER_28_3v3", "", "", ++ "HEADER_27_3v3", "", "", "", + "HEADER_29_1v8", "", "HEADER_7_1v8", "", + /* GPIO1 B0-B7 */ + "", "HEADER_31_1v8", "HEADER_33_1v8", "", + "HEADER_11_1v8", "HEADER_13_1v8", "", "", + /* GPIO1 C0-C7 */ +- "", "", "", "", ++ "", "HEADER_28_3v3", "", "", + "", "", "", "", + /* GPIO1 D0-D7 */ + "", "", "", "", +@@ -226,11 +226,11 @@ &gpio3 { + + &gpio4 { + gpio-line-names = /* GPIO4 A0-A7 */ +- "", "", "HEADER_37_3v3", "HEADER_32_3v3", +- "HEADER_36_3v3", "", "HEADER_35_3v3", "HEADER_38_3v3", ++ "", "", "HEADER_37_3v3", "HEADER_8_3v3", ++ "HEADER_10_3v3", "", "HEADER_32_3v3", "HEADER_35_3v3", + /* GPIO4 B0-B7 */ + "", "", "", "HEADER_40_3v3", +- "HEADER_8_3v3", "HEADER_10_3v3", "", "", ++ "HEADER_38_3v3", "HEADER_36_3v3", "", "", + /* GPIO4 C0-C7 */ + "", "", "", "", + "", "", "", "", +diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h +index 50e5f25d3024c..7780d343ef080 100644 +--- a/arch/arm64/include/asm/fpsimd.h ++++ b/arch/arm64/include/asm/fpsimd.h +@@ -386,6 +386,7 @@ extern void sme_alloc(struct task_struct *task, bool flush); + extern unsigned int sme_get_vl(void); + extern int sme_set_current_vl(unsigned long arg); + extern int sme_get_current_vl(void); ++extern void sme_suspend_exit(void); + + /* + * Return how many bytes of memory are required to store the full SME +@@ -421,6 +422,7 @@ static inline int sme_max_vl(void) { return 0; } + static inline int sme_max_virtualisable_vl(void) { return 0; } + static inline int sme_set_current_vl(unsigned long arg) { return -EINVAL; } + static inline int sme_get_current_vl(void) { return -EINVAL; } ++static inline void sme_suspend_exit(void) { } + + static inline size_t sme_state_size(struct task_struct const *task) + { +diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c +index f7d8f5d81cfe9..0898ac9979045 100644 +--- a/arch/arm64/kernel/fpsimd.c ++++ b/arch/arm64/kernel/fpsimd.c +@@ -1339,6 +1339,22 @@ void __init sme_setup(void) + get_sme_default_vl()); + } + ++void sme_suspend_exit(void) ++{ ++ u64 smcr = 0; ++ ++ if (!system_supports_sme()) ++ return; ++ ++ if (system_supports_fa64()) ++ smcr |= SMCR_ELx_FA64; ++ if (system_supports_sme2()) ++ smcr |= SMCR_ELx_EZT0; ++ ++ write_sysreg_s(smcr, SYS_SMCR_EL1); ++ write_sysreg_s(0, SYS_SMPRI_EL1); ++} ++ + #endif /* CONFIG_ARM64_SME */ + + static void sve_init_regs(void) +diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c +index eca4d04352118..eaaff94329cdd 100644 +--- a/arch/arm64/kernel/suspend.c ++++ b/arch/arm64/kernel/suspend.c +@@ -12,6 +12,7 @@ + #include <asm/daifflags.h> + #include <asm/debug-monitors.h> + #include <asm/exec.h> ++#include <asm/fpsimd.h> + #include <asm/mte.h> + #include <asm/memory.h> + #include <asm/mmu_context.h> +@@ -80,6 +81,8 @@ void notrace __cpu_suspend_exit(void) + */ + spectre_v4_enable_mitigation(NULL); + ++ sme_suspend_exit(); ++ + /* Restore additional feature-specific configuration */ + ptrauth_suspend_exit(); + } +diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c +index e2764d0ffa9f3..28a93074eca17 100644 +--- a/arch/arm64/kvm/vgic/vgic-its.c ++++ b/arch/arm64/kvm/vgic/vgic-its.c +@@ -468,6 +468,9 @@ static int its_sync_lpi_pending_table(struct kvm_vcpu *vcpu) + } + + irq = vgic_get_irq(vcpu->kvm, NULL, intids[i]); ++ if (!irq) ++ continue; ++ + raw_spin_lock_irqsave(&irq->irq_lock, flags); + irq->pending_latch = pendmask & (1U << bit_nr); + vgic_queue_irq_unlock(vcpu->kvm, irq, flags); +@@ -1432,6 +1435,8 @@ static int vgic_its_cmd_handle_movall(struct kvm *kvm, struct vgic_its *its, + + for (i = 0; i < irq_count; i++) { + irq = vgic_get_irq(kvm, NULL, intids[i]); ++ if (!irq) ++ continue; + + update_affinity(irq, vcpu2); + +diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig +index ee123820a4760..205956041d7d0 100644 +--- a/arch/loongarch/Kconfig ++++ b/arch/loongarch/Kconfig +@@ -11,6 +11,7 @@ config LOONGARCH + select ARCH_DISABLE_KASAN_INLINE + select ARCH_ENABLE_MEMORY_HOTPLUG + select ARCH_ENABLE_MEMORY_HOTREMOVE ++ select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE + select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI + select ARCH_HAS_CPU_FINALIZE_INIT + select ARCH_HAS_FORTIFY_SOURCE +@@ -97,6 +98,7 @@ config LOONGARCH + select HAVE_ARCH_KFENCE + select HAVE_ARCH_KGDB if PERF_EVENTS + select HAVE_ARCH_MMAP_RND_BITS if MMU ++ select HAVE_ARCH_SECCOMP + select HAVE_ARCH_SECCOMP_FILTER + select HAVE_ARCH_TRACEHOOK + select HAVE_ARCH_TRANSPARENT_HUGEPAGE +@@ -608,23 +610,6 @@ config RANDOMIZE_BASE_MAX_OFFSET + + This is limited by the size of the lower address memory, 256MB. + +-config SECCOMP +- bool "Enable seccomp to safely compute untrusted bytecode" +- depends on PROC_FS +- default y +- help +- This kernel feature is useful for number crunching applications +- that may need to compute untrusted bytecode during their +- execution. By using pipes or other transports made available to +- the process as file descriptors supporting the read/write +- syscalls, it's possible to isolate those applications in +- their own address space using seccomp. Once seccomp is +- enabled via /proc/<pid>/seccomp, it cannot be disabled +- and the task is only allowed to execute a few safe syscalls +- defined by each seccomp mode. +- +- If unsure, say Y. Only embedded should say N here. +- + endmenu + + config ARCH_SELECT_MEMORY_MODEL +@@ -643,10 +628,6 @@ config ARCH_SPARSEMEM_ENABLE + or have huge holes in the physical address space for other reasons. + See <file:Documentation/mm/numa.rst> for more. + +-config ARCH_ENABLE_THP_MIGRATION +- def_bool y +- depends on TRANSPARENT_HUGEPAGE +- + config ARCH_MEMORY_PROBE + def_bool y + depends on MEMORY_HOTPLUG +diff --git a/arch/loongarch/include/asm/acpi.h b/arch/loongarch/include/asm/acpi.h +index 8de6c4b83a61a..49e29b29996f0 100644 +--- a/arch/loongarch/include/asm/acpi.h ++++ b/arch/loongarch/include/asm/acpi.h +@@ -32,8 +32,10 @@ static inline bool acpi_has_cpu_in_madt(void) + return true; + } + ++#define MAX_CORE_PIC 256 ++ + extern struct list_head acpi_wakeup_device_list; +-extern struct acpi_madt_core_pic acpi_core_pic[NR_CPUS]; ++extern struct acpi_madt_core_pic acpi_core_pic[MAX_CORE_PIC]; + + extern int __init parse_acpi_topology(void); + +diff --git a/arch/loongarch/kernel/acpi.c b/arch/loongarch/kernel/acpi.c +index 8e00a754e5489..55d6a48c76a82 100644 +--- a/arch/loongarch/kernel/acpi.c ++++ b/arch/loongarch/kernel/acpi.c +@@ -29,11 +29,9 @@ int disabled_cpus; + + u64 acpi_saved_sp; + +-#define MAX_CORE_PIC 256 +- + #define PREFIX "ACPI: " + +-struct acpi_madt_core_pic acpi_core_pic[NR_CPUS]; ++struct acpi_madt_core_pic acpi_core_pic[MAX_CORE_PIC]; + + void __init __iomem * __acpi_map_table(unsigned long phys, unsigned long size) + { +diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c +index d183a745fb85d..b7c14a1242276 100644 +--- a/arch/loongarch/kernel/setup.c ++++ b/arch/loongarch/kernel/setup.c +@@ -366,6 +366,8 @@ void __init platform_init(void) + acpi_gbl_use_default_register_widths = false; + acpi_boot_table_init(); + #endif ++ ++ early_init_fdt_scan_reserved_mem(); + unflatten_and_copy_device_tree(); + + #ifdef CONFIG_NUMA +@@ -399,8 +401,6 @@ static void __init arch_mem_init(char **cmdline_p) + + check_kernel_sections_mem(); + +- early_init_fdt_scan_reserved_mem(); +- + /* + * In order to reduce the possibility of kernel panic when failed to + * get IO TLB memory under CONFIG_SWIOTLB, it is better to allocate +diff --git a/arch/loongarch/kernel/smp.c b/arch/loongarch/kernel/smp.c +index 2fbf541d7b4f6..378ffa78ffeb4 100644 +--- a/arch/loongarch/kernel/smp.c ++++ b/arch/loongarch/kernel/smp.c +@@ -88,6 +88,73 @@ void show_ipi_list(struct seq_file *p, int prec) + } + } + ++static inline void set_cpu_core_map(int cpu) ++{ ++ int i; ++ ++ cpumask_set_cpu(cpu, &cpu_core_setup_map); ++ ++ for_each_cpu(i, &cpu_core_setup_map) { ++ if (cpu_data[cpu].package == cpu_data[i].package) { ++ cpumask_set_cpu(i, &cpu_core_map[cpu]); ++ cpumask_set_cpu(cpu, &cpu_core_map[i]); ++ } ++ } ++} ++ ++static inline void set_cpu_sibling_map(int cpu) ++{ ++ int i; ++ ++ cpumask_set_cpu(cpu, &cpu_sibling_setup_map); ++ ++ for_each_cpu(i, &cpu_sibling_setup_map) { ++ if (cpus_are_siblings(cpu, i)) { ++ cpumask_set_cpu(i, &cpu_sibling_map[cpu]); ++ cpumask_set_cpu(cpu, &cpu_sibling_map[i]); ++ } ++ } ++} ++ ++static inline void clear_cpu_sibling_map(int cpu) ++{ ++ int i; ++ ++ for_each_cpu(i, &cpu_sibling_setup_map) { ++ if (cpus_are_siblings(cpu, i)) { ++ cpumask_clear_cpu(i, &cpu_sibling_map[cpu]); ++ cpumask_clear_cpu(cpu, &cpu_sibling_map[i]); ++ } ++ } ++ ++ cpumask_clear_cpu(cpu, &cpu_sibling_setup_map); ++} ++ ++/* ++ * Calculate a new cpu_foreign_map mask whenever a ++ * new cpu appears or disappears. ++ */ ++void calculate_cpu_foreign_map(void) ++{ ++ int i, k, core_present; ++ cpumask_t temp_foreign_map; ++ ++ /* Re-calculate the mask */ ++ cpumask_clear(&temp_foreign_map); ++ for_each_online_cpu(i) { ++ core_present = 0; ++ for_each_cpu(k, &temp_foreign_map) ++ if (cpus_are_siblings(i, k)) ++ core_present = 1; ++ if (!core_present) ++ cpumask_set_cpu(i, &temp_foreign_map); ++ } ++ ++ for_each_online_cpu(i) ++ cpumask_andnot(&cpu_foreign_map[i], ++ &temp_foreign_map, &cpu_sibling_map[i]); ++} ++ + /* Send mailbox buffer via Mail_Send */ + static void csr_mail_send(uint64_t data, int cpu, int mailbox) + { +@@ -300,6 +367,7 @@ int loongson_cpu_disable(void) + numa_remove_cpu(cpu); + #endif + set_cpu_online(cpu, false); ++ clear_cpu_sibling_map(cpu); + calculate_cpu_foreign_map(); + local_irq_save(flags); + irq_migrate_all_off_this_cpu(); +@@ -334,6 +402,7 @@ void __noreturn arch_cpu_idle_dead(void) + addr = iocsr_read64(LOONGARCH_IOCSR_MBUF0); + } while (addr == 0); + ++ local_irq_disable(); + init_fn = (void *)TO_CACHE(addr); + iocsr_write32(0xffffffff, LOONGARCH_IOCSR_IPI_CLEAR); + +@@ -376,59 +445,6 @@ static int __init ipi_pm_init(void) + core_initcall(ipi_pm_init); + #endif + +-static inline void set_cpu_sibling_map(int cpu) +-{ +- int i; +- +- cpumask_set_cpu(cpu, &cpu_sibling_setup_map); +- +- for_each_cpu(i, &cpu_sibling_setup_map) { +- if (cpus_are_siblings(cpu, i)) { +- cpumask_set_cpu(i, &cpu_sibling_map[cpu]); +- cpumask_set_cpu(cpu, &cpu_sibling_map[i]); +- } +- } +-} +- +-static inline void set_cpu_core_map(int cpu) +-{ +- int i; +- +- cpumask_set_cpu(cpu, &cpu_core_setup_map); +- +- for_each_cpu(i, &cpu_core_setup_map) { +- if (cpu_data[cpu].package == cpu_data[i].package) { +- cpumask_set_cpu(i, &cpu_core_map[cpu]); +- cpumask_set_cpu(cpu, &cpu_core_map[i]); +- } +- } +-} +- +-/* +- * Calculate a new cpu_foreign_map mask whenever a +- * new cpu appears or disappears. +- */ +-void calculate_cpu_foreign_map(void) +-{ +- int i, k, core_present; +- cpumask_t temp_foreign_map; +- +- /* Re-calculate the mask */ +- cpumask_clear(&temp_foreign_map); +- for_each_online_cpu(i) { +- core_present = 0; +- for_each_cpu(k, &temp_foreign_map) +- if (cpus_are_siblings(i, k)) +- core_present = 1; +- if (!core_present) +- cpumask_set_cpu(i, &temp_foreign_map); +- } +- +- for_each_online_cpu(i) +- cpumask_andnot(&cpu_foreign_map[i], +- &temp_foreign_map, &cpu_sibling_map[i]); +-} +- + /* Preload SMP state for boot cpu */ + void smp_prepare_boot_cpu(void) + { +diff --git a/arch/loongarch/vdso/Makefile b/arch/loongarch/vdso/Makefile +index c74c9921304f2..f597cd08a96be 100644 +--- a/arch/loongarch/vdso/Makefile ++++ b/arch/loongarch/vdso/Makefile +@@ -2,6 +2,7 @@ + # Objects to go into the VDSO. + + KASAN_SANITIZE := n ++UBSAN_SANITIZE := n + KCOV_INSTRUMENT := n + + # Include the generic Makefile to check the built vdso. +diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c +index 246c6a6b02614..5b778995d4483 100644 +--- a/arch/mips/kernel/traps.c ++++ b/arch/mips/kernel/traps.c +@@ -2007,7 +2007,13 @@ unsigned long vi_handlers[64]; + + void reserve_exception_space(phys_addr_t addr, unsigned long size) + { +- memblock_reserve(addr, size); ++ /* ++ * reserve exception space on CPUs other than CPU0 ++ * is too late, since memblock is unavailable when APs ++ * up ++ */ ++ if (smp_processor_id() == 0) ++ memblock_reserve(addr, size); + } + + void __init *set_except_vector(int n, void *addr) +diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c +index e95a977ba5f37..bf73562706b2e 100644 +--- a/arch/parisc/kernel/processor.c ++++ b/arch/parisc/kernel/processor.c +@@ -172,7 +172,6 @@ static int __init processor_probe(struct parisc_device *dev) + p->cpu_num = cpu_info.cpu_num; + p->cpu_loc = cpu_info.cpu_loc; + +- set_cpu_possible(cpuid, true); + store_cpu_topology(cpuid); + + #ifdef CONFIG_SMP +@@ -474,13 +473,6 @@ static struct parisc_driver cpu_driver __refdata = { + */ + void __init processor_init(void) + { +- unsigned int cpu; +- + reset_cpu_topology(); +- +- /* reset possible mask. We will mark those which are possible. */ +- for_each_possible_cpu(cpu) +- set_cpu_possible(cpu, false); +- + register_parisc_driver(&cpu_driver); + } +diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c +index 27ae40a443b80..f7e0fee5ee55a 100644 +--- a/arch/parisc/kernel/unwind.c ++++ b/arch/parisc/kernel/unwind.c +@@ -228,10 +228,8 @@ static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int + #ifdef CONFIG_IRQSTACKS + extern void * const _call_on_stack; + #endif /* CONFIG_IRQSTACKS */ +- void *ptr; + +- ptr = dereference_kernel_function_descriptor(&handle_interruption); +- if (pc_is_kernel_fn(pc, ptr)) { ++ if (pc_is_kernel_fn(pc, handle_interruption)) { + struct pt_regs *regs = (struct pt_regs *)(info->sp - frame_size - PT_SZ_ALGN); + dbg("Unwinding through handle_interruption()\n"); + info->prev_sp = regs->gr[30]; +@@ -239,13 +237,13 @@ static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int + return 1; + } + +- if (pc_is_kernel_fn(pc, ret_from_kernel_thread) || +- pc_is_kernel_fn(pc, syscall_exit)) { ++ if (pc == (unsigned long)&ret_from_kernel_thread || ++ pc == (unsigned long)&syscall_exit) { + info->prev_sp = info->prev_ip = 0; + return 1; + } + +- if (pc_is_kernel_fn(pc, intr_return)) { ++ if (pc == (unsigned long)&intr_return) { + struct pt_regs *regs; + + dbg("Found intr_return()\n"); +@@ -257,14 +255,14 @@ static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int + } + + if (pc_is_kernel_fn(pc, _switch_to) || +- pc_is_kernel_fn(pc, _switch_to_ret)) { ++ pc == (unsigned long)&_switch_to_ret) { + info->prev_sp = info->sp - CALLEE_SAVE_FRAME_SIZE; + info->prev_ip = *(unsigned long *)(info->prev_sp - RP_OFFSET); + return 1; + } + + #ifdef CONFIG_IRQSTACKS +- if (pc_is_kernel_fn(pc, _call_on_stack)) { ++ if (pc == (unsigned long)&_call_on_stack) { + info->prev_sp = *(unsigned long *)(info->sp - FRAME_SIZE - REG_SZ); + info->prev_ip = *(unsigned long *)(info->sp - FRAME_SIZE - RP_OFFSET); + return 1; +diff --git a/arch/powerpc/include/asm/ppc-pci.h b/arch/powerpc/include/asm/ppc-pci.h +index d9fcff5750271..2689e7139b9ea 100644 +--- a/arch/powerpc/include/asm/ppc-pci.h ++++ b/arch/powerpc/include/asm/ppc-pci.h +@@ -30,6 +30,16 @@ void *pci_traverse_device_nodes(struct device_node *start, + void *data); + extern void pci_devs_phb_init_dynamic(struct pci_controller *phb); + ++#if defined(CONFIG_IOMMU_API) && (defined(CONFIG_PPC_PSERIES) || \ ++ defined(CONFIG_PPC_POWERNV)) ++extern void ppc_iommu_register_device(struct pci_controller *phb); ++extern void ppc_iommu_unregister_device(struct pci_controller *phb); ++#else ++static inline void ppc_iommu_register_device(struct pci_controller *phb) { } ++static inline void ppc_iommu_unregister_device(struct pci_controller *phb) { } ++#endif ++ ++ + /* From rtas_pci.h */ + extern void init_pci_config_tokens (void); + extern unsigned long get_phb_buid (struct device_node *); +diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c +index df17b33b89d13..2c0173e7094da 100644 +--- a/arch/powerpc/kernel/iommu.c ++++ b/arch/powerpc/kernel/iommu.c +@@ -1341,7 +1341,7 @@ static struct iommu_device *spapr_tce_iommu_probe_device(struct device *dev) + struct pci_controller *hose; + + if (!dev_is_pci(dev)) +- return ERR_PTR(-EPERM); ++ return ERR_PTR(-ENODEV); + + pdev = to_pci_dev(dev); + hose = pdev->bus->sysdata; +@@ -1390,6 +1390,21 @@ static const struct attribute_group *spapr_tce_iommu_groups[] = { + NULL, + }; + ++void ppc_iommu_register_device(struct pci_controller *phb) ++{ ++ iommu_device_sysfs_add(&phb->iommu, phb->parent, ++ spapr_tce_iommu_groups, "iommu-phb%04x", ++ phb->global_number); ++ iommu_device_register(&phb->iommu, &spapr_tce_iommu_ops, ++ phb->parent); ++} ++ ++void ppc_iommu_unregister_device(struct pci_controller *phb) ++{ ++ iommu_device_unregister(&phb->iommu); ++ iommu_device_sysfs_remove(&phb->iommu); ++} ++ + /* + * This registers IOMMU devices of PHBs. This needs to happen + * after core_initcall(iommu_init) + postcore_initcall(pci_driver_init) and +@@ -1400,11 +1415,7 @@ static int __init spapr_tce_setup_phb_iommus_initcall(void) + struct pci_controller *hose; + + list_for_each_entry(hose, &hose_list, list_node) { +- iommu_device_sysfs_add(&hose->iommu, hose->parent, +- spapr_tce_iommu_groups, "iommu-phb%04x", +- hose->global_number); +- iommu_device_register(&hose->iommu, &spapr_tce_iommu_ops, +- hose->parent); ++ ppc_iommu_register_device(hose); + } + return 0; + } +diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c +index 002a7573a5d44..b5c6af0bef81e 100644 +--- a/arch/powerpc/kvm/book3s_hv.c ++++ b/arch/powerpc/kvm/book3s_hv.c +@@ -391,6 +391,24 @@ static void kvmppc_set_pvr_hv(struct kvm_vcpu *vcpu, u32 pvr) + /* Dummy value used in computing PCR value below */ + #define PCR_ARCH_31 (PCR_ARCH_300 << 1) + ++static inline unsigned long map_pcr_to_cap(unsigned long pcr) ++{ ++ unsigned long cap = 0; ++ ++ switch (pcr) { ++ case PCR_ARCH_300: ++ cap = H_GUEST_CAP_POWER9; ++ break; ++ case PCR_ARCH_31: ++ cap = H_GUEST_CAP_POWER10; ++ break; ++ default: ++ break; ++ } ++ ++ return cap; ++} ++ + static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat) + { + unsigned long host_pcr_bit = 0, guest_pcr_bit = 0, cap = 0; +@@ -424,11 +442,9 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat) + break; + case PVR_ARCH_300: + guest_pcr_bit = PCR_ARCH_300; +- cap = H_GUEST_CAP_POWER9; + break; + case PVR_ARCH_31: + guest_pcr_bit = PCR_ARCH_31; +- cap = H_GUEST_CAP_POWER10; + break; + default: + return -EINVAL; +@@ -440,6 +456,12 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat) + return -EINVAL; + + if (kvmhv_on_pseries() && kvmhv_is_nestedv2()) { ++ /* ++ * 'arch_compat == 0' would mean the guest should default to ++ * L1's compatibility. In this case, the guest would pick ++ * host's PCR and evaluate the corresponding capabilities. ++ */ ++ cap = map_pcr_to_cap(guest_pcr_bit); + if (!(cap & nested_capabilities)) + return -EINVAL; + } +diff --git a/arch/powerpc/kvm/book3s_hv_nestedv2.c b/arch/powerpc/kvm/book3s_hv_nestedv2.c +index fd3c4f2d94805..f354af7e85114 100644 +--- a/arch/powerpc/kvm/book3s_hv_nestedv2.c ++++ b/arch/powerpc/kvm/book3s_hv_nestedv2.c +@@ -138,6 +138,7 @@ static int gs_msg_ops_vcpu_fill_info(struct kvmppc_gs_buff *gsb, + vector128 v; + int rc, i; + u16 iden; ++ u32 arch_compat = 0; + + vcpu = gsm->data; + +@@ -347,8 +348,23 @@ static int gs_msg_ops_vcpu_fill_info(struct kvmppc_gs_buff *gsb, + break; + } + case KVMPPC_GSID_LOGICAL_PVR: +- rc = kvmppc_gse_put_u32(gsb, iden, +- vcpu->arch.vcore->arch_compat); ++ /* ++ * Though 'arch_compat == 0' would mean the default ++ * compatibility, arch_compat, being a Guest Wide ++ * Element, cannot be filled with a value of 0 in GSB ++ * as this would result into a kernel trap. ++ * Hence, when `arch_compat == 0`, arch_compat should ++ * default to L1's PVR. ++ */ ++ if (!vcpu->arch.vcore->arch_compat) { ++ if (cpu_has_feature(CPU_FTR_ARCH_31)) ++ arch_compat = PVR_ARCH_31; ++ else if (cpu_has_feature(CPU_FTR_ARCH_300)) ++ arch_compat = PVR_ARCH_300; ++ } else { ++ arch_compat = vcpu->arch.vcore->arch_compat; ++ } ++ rc = kvmppc_gse_put_u32(gsb, iden, arch_compat); + break; + } + +diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c +index 4ba8245681192..4448386268d99 100644 +--- a/arch/powerpc/platforms/pseries/pci_dlpar.c ++++ b/arch/powerpc/platforms/pseries/pci_dlpar.c +@@ -35,6 +35,8 @@ struct pci_controller *init_phb_dynamic(struct device_node *dn) + + pseries_msi_allocate_domains(phb); + ++ ppc_iommu_register_device(phb); ++ + /* Create EEH devices for the PHB */ + eeh_phb_pe_create(phb); + +@@ -76,6 +78,8 @@ int remove_phb_dynamic(struct pci_controller *phb) + } + } + ++ ppc_iommu_unregister_device(phb); ++ + pseries_msi_free_domains(phb); + + /* Keep a reference so phb isn't freed yet */ +diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c +index 676ac74026a82..52a44e353796c 100644 +--- a/arch/s390/pci/pci.c ++++ b/arch/s390/pci/pci.c +@@ -252,7 +252,7 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res, + /* combine single writes by using store-block insn */ + void __iowrite64_copy(void __iomem *to, const void *from, size_t count) + { +- zpci_memcpy_toio(to, from, count); ++ zpci_memcpy_toio(to, from, count * 8); + } + + void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size, +diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile +index 5f60359361312..2a03daa68f285 100644 +--- a/arch/sparc/Makefile ++++ b/arch/sparc/Makefile +@@ -60,7 +60,7 @@ libs-y += arch/sparc/prom/ + libs-y += arch/sparc/lib/ + + drivers-$(CONFIG_PM) += arch/sparc/power/ +-drivers-$(CONFIG_FB) += arch/sparc/video/ ++drivers-$(CONFIG_FB_CORE) += arch/sparc/video/ + + boot := arch/sparc/boot + +diff --git a/arch/sparc/video/Makefile b/arch/sparc/video/Makefile +index 6baddbd58e4db..d4d83f1702c61 100644 +--- a/arch/sparc/video/Makefile ++++ b/arch/sparc/video/Makefile +@@ -1,3 +1,3 @@ + # SPDX-License-Identifier: GPL-2.0-only + +-obj-$(CONFIG_FB) += fbdev.o ++obj-$(CONFIG_FB_CORE) += fbdev.o +diff --git a/arch/x86/entry/entry.S b/arch/x86/entry/entry.S +index 8c8d38f0cb1df..0033790499245 100644 +--- a/arch/x86/entry/entry.S ++++ b/arch/x86/entry/entry.S +@@ -6,6 +6,9 @@ + #include <linux/export.h> + #include <linux/linkage.h> + #include <asm/msr-index.h> ++#include <asm/unwind_hints.h> ++#include <asm/segment.h> ++#include <asm/cache.h> + + .pushsection .noinstr.text, "ax" + +@@ -20,3 +23,23 @@ SYM_FUNC_END(entry_ibpb) + EXPORT_SYMBOL_GPL(entry_ibpb); + + .popsection ++ ++/* ++ * Define the VERW operand that is disguised as entry code so that ++ * it can be referenced with KPTI enabled. This ensure 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) ++ UNWIND_HINT_UNDEFINED ++ ANNOTATE_NOENDBR ++ .word __KERNEL_DS ++.align L1_CACHE_BYTES, 0xcc ++SYM_CODE_END(mds_verw_sel); ++/* For KVM */ ++EXPORT_SYMBOL_GPL(mds_verw_sel); ++ ++.popsection ++ +diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h +index 3e973ff20e235..caf4cf2e1036f 100644 +--- a/arch/x86/include/asm/cpufeatures.h ++++ b/arch/x86/include/asm/cpufeatures.h +@@ -97,7 +97,7 @@ + #define X86_FEATURE_SYSENTER32 ( 3*32+15) /* "" sysenter in IA32 userspace */ + #define X86_FEATURE_REP_GOOD ( 3*32+16) /* REP microcode works well */ + #define X86_FEATURE_AMD_LBR_V2 ( 3*32+17) /* AMD Last Branch Record Extension Version 2 */ +-/* FREE, was #define X86_FEATURE_LFENCE_RDTSC ( 3*32+18) "" LFENCE synchronizes RDTSC */ ++#define X86_FEATURE_CLEAR_CPU_BUF ( 3*32+18) /* "" Clear CPU buffers using VERW */ + #define X86_FEATURE_ACC_POWER ( 3*32+19) /* AMD Accumulated Power Mechanism */ + #define X86_FEATURE_NOPL ( 3*32+20) /* The NOPL (0F 1F) instructions */ + #define X86_FEATURE_ALWAYS ( 3*32+21) /* "" Always-present feature */ +diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h +index f93e9b96927ac..2519615936e95 100644 +--- a/arch/x86/include/asm/nospec-branch.h ++++ b/arch/x86/include/asm/nospec-branch.h +@@ -315,6 +315,17 @@ + #endif + .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. ++ * ++ * Note: Only the memory operand variant of VERW clears the CPU buffers. ++ */ ++.macro CLEAR_CPU_BUFFERS ++ ALTERNATIVE "", __stringify(verw _ASM_RIP(mds_verw_sel)), X86_FEATURE_CLEAR_CPU_BUF ++.endm ++ + #else /* __ASSEMBLY__ */ + + #define ANNOTATE_RETPOLINE_SAFE \ +@@ -536,6 +547,8 @@ DECLARE_STATIC_KEY_FALSE(switch_mm_cond_l1d_flush); + + DECLARE_STATIC_KEY_FALSE(mmio_stale_data_clear); + ++extern u16 mds_verw_sel; ++ + #include <asm/segment.h> + + /** +diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c +index c876f1d36a81a..832f4413d96a8 100644 +--- a/arch/x86/kernel/traps.c ++++ b/arch/x86/kernel/traps.c +@@ -591,7 +591,7 @@ static bool try_fixup_enqcmd_gp(void) + if (!mm_valid_pasid(current->mm)) + return false; + +- pasid = current->mm->pasid; ++ pasid = mm_get_enqcmd_pasid(current->mm); + + /* + * Did this thread already have its PASID activated? +diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c +index b29ceb19e46ec..9d63cfff1fd41 100644 +--- a/arch/x86/mm/numa.c ++++ b/arch/x86/mm/numa.c +@@ -964,7 +964,7 @@ static int __init cmp_memblk(const void *a, const void *b) + const struct numa_memblk *ma = *(const struct numa_memblk **)a; + const struct numa_memblk *mb = *(const struct numa_memblk **)b; + +- return ma->start - mb->start; ++ return (ma->start > mb->start) - (ma->start < mb->start); + } + + static struct numa_memblk *numa_memblk_list[NR_NODE_MEMBLKS] __initdata; +@@ -974,14 +974,12 @@ static struct numa_memblk *numa_memblk_list[NR_NODE_MEMBLKS] __initdata; + * @start: address to begin fill + * @end: address to end fill + * +- * Find and extend numa_meminfo memblks to cover the @start-@end +- * physical address range, such that the first memblk includes +- * @start, the last memblk includes @end, and any gaps in between +- * are filled. ++ * Find and extend numa_meminfo memblks to cover the physical ++ * address range @start-@end + * + * RETURNS: + * 0 : Success +- * NUMA_NO_MEMBLK : No memblk exists in @start-@end range ++ * NUMA_NO_MEMBLK : No memblks exist in address range @start-@end + */ + + int __init numa_fill_memblks(u64 start, u64 end) +@@ -993,17 +991,14 @@ int __init numa_fill_memblks(u64 start, u64 end) + + /* + * Create a list of pointers to numa_meminfo memblks that +- * overlap start, end. Exclude (start == bi->end) since +- * end addresses in both a CFMWS range and a memblk range +- * are exclusive. +- * +- * This list of pointers is used to make in-place changes +- * that fill out the numa_meminfo memblks. ++ * overlap start, end. The list is used to make in-place ++ * changes that fill out the numa_meminfo memblks. + */ + for (int i = 0; i < mi->nr_blks; i++) { + struct numa_memblk *bi = &mi->blk[i]; + +- if (start < bi->end && end >= bi->start) { ++ if (memblock_addrs_overlap(start, end - start, bi->start, ++ bi->end - bi->start)) { + blk[count] = &mi->blk[i]; + count++; + } +diff --git a/block/blk-map.c b/block/blk-map.c +index 8584babf3ea0c..71210cdb34426 100644 +--- a/block/blk-map.c ++++ b/block/blk-map.c +@@ -205,12 +205,19 @@ static int bio_copy_user_iov(struct request *rq, struct rq_map_data *map_data, + /* + * success + */ +- if ((iov_iter_rw(iter) == WRITE && +- (!map_data || !map_data->null_mapped)) || +- (map_data && map_data->from_user)) { ++ if (iov_iter_rw(iter) == WRITE && ++ (!map_data || !map_data->null_mapped)) { + ret = bio_copy_from_iter(bio, iter); + if (ret) + goto cleanup; ++ } else if (map_data && map_data->from_user) { ++ struct iov_iter iter2 = *iter; ++ ++ /* This is the copy-in part of SG_DXFER_TO_FROM_DEV. */ ++ iter2.data_source = ITER_SOURCE; ++ ret = bio_copy_from_iter(bio, &iter2); ++ if (ret) ++ goto cleanup; + } else { + if (bmd->is_our_pages) + zero_fill_bio(bio); +diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c +index 7906030176538..c856c417a1451 100644 +--- a/drivers/accel/ivpu/ivpu_drv.c ++++ b/drivers/accel/ivpu/ivpu_drv.c +@@ -479,9 +479,8 @@ static int ivpu_pci_init(struct ivpu_device *vdev) + /* Clear any pending errors */ + pcie_capability_clear_word(pdev, PCI_EXP_DEVSTA, 0x3f); + +- /* VPU 37XX does not require 10m D3hot delay */ +- if (ivpu_hw_gen(vdev) == IVPU_HW_37XX) +- pdev->d3hot_delay = 0; ++ /* NPU does not require 10m D3hot delay */ ++ pdev->d3hot_delay = 0; + + ret = pcim_enable_device(pdev); + if (ret) { +diff --git a/drivers/accel/ivpu/ivpu_hw_37xx.c b/drivers/accel/ivpu/ivpu_hw_37xx.c +index d530384f8d607..e658fcf849f7a 100644 +--- a/drivers/accel/ivpu/ivpu_hw_37xx.c ++++ b/drivers/accel/ivpu/ivpu_hw_37xx.c +@@ -523,7 +523,7 @@ static void ivpu_boot_no_snoop_enable(struct ivpu_device *vdev) + u32 val = REGV_RD32(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES); + + val = REG_SET_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, NOSNOOP_OVERRIDE_EN, val); +- val = REG_SET_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, AW_NOSNOOP_OVERRIDE, val); ++ val = REG_CLR_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, AW_NOSNOOP_OVERRIDE, val); + val = REG_SET_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, AR_NOSNOOP_OVERRIDE, val); + + REGV_WR32(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, val); +diff --git a/drivers/accel/ivpu/ivpu_hw_40xx.c b/drivers/accel/ivpu/ivpu_hw_40xx.c +index e691c49c98410..40f9ee99eccc1 100644 +--- a/drivers/accel/ivpu/ivpu_hw_40xx.c ++++ b/drivers/accel/ivpu/ivpu_hw_40xx.c +@@ -24,7 +24,7 @@ + #define SKU_HW_ID_SHIFT 16u + #define SKU_HW_ID_MASK 0xffff0000u + +-#define PLL_CONFIG_DEFAULT 0x1 ++#define PLL_CONFIG_DEFAULT 0x0 + #define PLL_CDYN_DEFAULT 0x80 + #define PLL_EPP_DEFAULT 0x80 + #define PLL_REF_CLK_FREQ (50 * 1000000) +@@ -526,7 +526,7 @@ static void ivpu_boot_no_snoop_enable(struct ivpu_device *vdev) + u32 val = REGV_RD32(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES); + + val = REG_SET_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, SNOOP_OVERRIDE_EN, val); +- val = REG_CLR_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, AW_SNOOP_OVERRIDE, val); ++ val = REG_SET_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, AW_SNOOP_OVERRIDE, val); + val = REG_CLR_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, AR_SNOOP_OVERRIDE, val); + + REGV_WR32(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, val); +@@ -700,7 +700,6 @@ static int ivpu_hw_40xx_info_init(struct ivpu_device *vdev) + { + struct ivpu_hw_info *hw = vdev->hw; + u32 tile_disable; +- u32 tile_enable; + u32 fuse; + + fuse = REGB_RD32(VPU_40XX_BUTTRESS_TILE_FUSE); +@@ -721,10 +720,6 @@ static int ivpu_hw_40xx_info_init(struct ivpu_device *vdev) + else + ivpu_dbg(vdev, MISC, "Fuse: All %d tiles enabled\n", TILE_MAX_NUM); + +- tile_enable = (~tile_disable) & TILE_MAX_MASK; +- +- hw->sku = REG_SET_FLD_NUM(SKU, HW_ID, LNL_HW_ID, hw->sku); +- hw->sku = REG_SET_FLD_NUM(SKU, TILE, tile_enable, hw->sku); + hw->tile_fuse = tile_disable; + hw->pll.profiling_freq = PLL_PROFILING_FREQ_DEFAULT; + +diff --git a/drivers/accel/ivpu/ivpu_mmu.c b/drivers/accel/ivpu/ivpu_mmu.c +index 2538c78fbebe2..9898946174fd9 100644 +--- a/drivers/accel/ivpu/ivpu_mmu.c ++++ b/drivers/accel/ivpu/ivpu_mmu.c +@@ -533,7 +533,6 @@ static int ivpu_mmu_reset(struct ivpu_device *vdev) + mmu->cmdq.cons = 0; + + memset(mmu->evtq.base, 0, IVPU_MMU_EVTQ_SIZE); +- clflush_cache_range(mmu->evtq.base, IVPU_MMU_EVTQ_SIZE); + mmu->evtq.prod = 0; + mmu->evtq.cons = 0; + +@@ -847,8 +846,6 @@ static u32 *ivpu_mmu_get_event(struct ivpu_device *vdev) + if (!CIRC_CNT(IVPU_MMU_Q_IDX(evtq->prod), IVPU_MMU_Q_IDX(evtq->cons), IVPU_MMU_Q_COUNT)) + return NULL; + +- clflush_cache_range(evt, IVPU_MMU_EVTQ_CMD_SIZE); +- + evtq->cons = (evtq->cons + 1) & IVPU_MMU_Q_WRAP_MASK; + REGV_WR32(IVPU_MMU_REG_EVTQ_CONS_SEC, evtq->cons); + +diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c +index 3a5f3255f51b3..da2e74fce2d99 100644 +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -48,6 +48,7 @@ enum { + enum board_ids { + /* board IDs by feature in alphabetical order */ + board_ahci, ++ board_ahci_43bit_dma, + board_ahci_ign_iferr, + board_ahci_low_power, + board_ahci_no_debounce_delay, +@@ -128,6 +129,13 @@ static const struct ata_port_info ahci_port_info[] = { + .udma_mask = ATA_UDMA6, + .port_ops = &ahci_ops, + }, ++ [board_ahci_43bit_dma] = { ++ AHCI_HFLAGS (AHCI_HFLAG_43BIT_ONLY), ++ .flags = AHCI_FLAG_COMMON, ++ .pio_mask = ATA_PIO4, ++ .udma_mask = ATA_UDMA6, ++ .port_ops = &ahci_ops, ++ }, + [board_ahci_ign_iferr] = { + AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR), + .flags = AHCI_FLAG_COMMON, +@@ -597,14 +605,14 @@ static const struct pci_device_id ahci_pci_tbl[] = { + { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ + { PCI_VDEVICE(PROMISE, 0x3781), board_ahci }, /* FastTrak TX8660 ahci-mode */ + +- /* Asmedia */ +- { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci }, /* ASM1060 */ +- { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci }, /* ASM1060 */ +- { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ +- { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ +- { PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci }, /* ASM1061R */ +- { PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci }, /* ASM1062R */ +- { PCI_VDEVICE(ASMEDIA, 0x0624), board_ahci }, /* ASM1062+JMB575 */ ++ /* ASMedia */ ++ { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci_43bit_dma }, /* ASM1060 */ ++ { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci_43bit_dma }, /* ASM1060 */ ++ { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci_43bit_dma }, /* ASM1061 */ ++ { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci_43bit_dma }, /* ASM1061/1062 */ ++ { PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci_43bit_dma }, /* ASM1061R */ ++ { PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci_43bit_dma }, /* ASM1062R */ ++ { PCI_VDEVICE(ASMEDIA, 0x0624), board_ahci_43bit_dma }, /* ASM1062+JMB575 */ + { PCI_VDEVICE(ASMEDIA, 0x1062), board_ahci }, /* ASM1062A */ + { PCI_VDEVICE(ASMEDIA, 0x1064), board_ahci }, /* ASM1064 */ + { PCI_VDEVICE(ASMEDIA, 0x1164), board_ahci }, /* ASM1164 */ +@@ -663,6 +671,11 @@ MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets"); + static void ahci_pci_save_initial_config(struct pci_dev *pdev, + struct ahci_host_priv *hpriv) + { ++ if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && pdev->device == 0x1166) { ++ dev_info(&pdev->dev, "ASM1166 has only six ports\n"); ++ hpriv->saved_port_map = 0x3f; ++ } ++ + if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) { + dev_info(&pdev->dev, "JMB361 has only one port\n"); + hpriv->saved_port_map = 1; +@@ -949,11 +962,20 @@ static int ahci_pci_device_resume(struct device *dev) + + #endif /* CONFIG_PM */ + +-static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) ++static int ahci_configure_dma_masks(struct pci_dev *pdev, ++ struct ahci_host_priv *hpriv) + { +- const int dma_bits = using_dac ? 64 : 32; ++ int dma_bits; + int rc; + ++ if (hpriv->cap & HOST_CAP_64) { ++ dma_bits = 64; ++ if (hpriv->flags & AHCI_HFLAG_43BIT_ONLY) ++ dma_bits = 43; ++ } else { ++ dma_bits = 32; ++ } ++ + /* + * If the device fixup already set the dma_mask to some non-standard + * value, don't extend it here. This happens on STA2X11, for example. +@@ -1926,7 +1948,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) + ahci_gtf_filter_workaround(host); + + /* initialize adapter */ +- rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64); ++ rc = ahci_configure_dma_masks(pdev, hpriv); + if (rc) + return rc; + +diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h +index 4bae95b06ae3c..df8f8a1a3a34c 100644 +--- a/drivers/ata/ahci.h ++++ b/drivers/ata/ahci.h +@@ -247,6 +247,7 @@ enum { + AHCI_HFLAG_SUSPEND_PHYS = BIT(26), /* handle PHYs during + suspend/resume */ + AHCI_HFLAG_NO_SXS = BIT(28), /* SXS not supported */ ++ AHCI_HFLAG_43BIT_ONLY = BIT(29), /* 43bit DMA addr limit */ + + /* ap->flags bits */ + +diff --git a/drivers/ata/ahci_ceva.c b/drivers/ata/ahci_ceva.c +index 64f7f7d6ba84e..11a2c199a7c24 100644 +--- a/drivers/ata/ahci_ceva.c ++++ b/drivers/ata/ahci_ceva.c +@@ -88,7 +88,6 @@ struct ceva_ahci_priv { + u32 axicc; + bool is_cci_enabled; + int flags; +- struct reset_control *rst; + }; + + static unsigned int ceva_ahci_read_id(struct ata_device *dev, +@@ -189,6 +188,60 @@ static const struct scsi_host_template ahci_platform_sht = { + AHCI_SHT(DRV_NAME), + }; + ++static int ceva_ahci_platform_enable_resources(struct ahci_host_priv *hpriv) ++{ ++ int rc, i; ++ ++ rc = ahci_platform_enable_regulators(hpriv); ++ if (rc) ++ return rc; ++ ++ rc = ahci_platform_enable_clks(hpriv); ++ if (rc) ++ goto disable_regulator; ++ ++ /* Assert the controller reset */ ++ rc = ahci_platform_assert_rsts(hpriv); ++ if (rc) ++ goto disable_clks; ++ ++ for (i = 0; i < hpriv->nports; i++) { ++ rc = phy_init(hpriv->phys[i]); ++ if (rc) ++ goto disable_rsts; ++ } ++ ++ /* De-assert the controller reset */ ++ ahci_platform_deassert_rsts(hpriv); ++ ++ for (i = 0; i < hpriv->nports; i++) { ++ rc = phy_power_on(hpriv->phys[i]); ++ if (rc) { ++ phy_exit(hpriv->phys[i]); ++ goto disable_phys; ++ } ++ } ++ ++ return 0; ++ ++disable_rsts: ++ ahci_platform_deassert_rsts(hpriv); ++ ++disable_phys: ++ while (--i >= 0) { ++ phy_power_off(hpriv->phys[i]); ++ phy_exit(hpriv->phys[i]); ++ } ++ ++disable_clks: ++ ahci_platform_disable_clks(hpriv); ++ ++disable_regulator: ++ ahci_platform_disable_regulators(hpriv); ++ ++ return rc; ++} ++ + static int ceva_ahci_probe(struct platform_device *pdev) + { + struct device_node *np = pdev->dev.of_node; +@@ -203,47 +256,19 @@ static int ceva_ahci_probe(struct platform_device *pdev) + return -ENOMEM; + + cevapriv->ahci_pdev = pdev; +- +- cevapriv->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, +- NULL); +- if (IS_ERR(cevapriv->rst)) +- dev_err_probe(&pdev->dev, PTR_ERR(cevapriv->rst), +- "failed to get reset\n"); +- + hpriv = ahci_platform_get_resources(pdev, 0); + if (IS_ERR(hpriv)) + return PTR_ERR(hpriv); + +- if (!cevapriv->rst) { +- rc = ahci_platform_enable_resources(hpriv); +- if (rc) +- return rc; +- } else { +- int i; ++ hpriv->rsts = devm_reset_control_get_optional_exclusive(&pdev->dev, ++ NULL); ++ if (IS_ERR(hpriv->rsts)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(hpriv->rsts), ++ "failed to get reset\n"); + +- rc = ahci_platform_enable_clks(hpriv); +- if (rc) +- return rc; +- /* Assert the controller reset */ +- reset_control_assert(cevapriv->rst); +- +- for (i = 0; i < hpriv->nports; i++) { +- rc = phy_init(hpriv->phys[i]); +- if (rc) +- return rc; +- } +- +- /* De-assert the controller reset */ +- reset_control_deassert(cevapriv->rst); +- +- for (i = 0; i < hpriv->nports; i++) { +- rc = phy_power_on(hpriv->phys[i]); +- if (rc) { +- phy_exit(hpriv->phys[i]); +- return rc; +- } +- } +- } ++ rc = ceva_ahci_platform_enable_resources(hpriv); ++ if (rc) ++ return rc; + + if (of_property_read_bool(np, "ceva,broken-gen2")) + cevapriv->flags = CEVA_FLAG_BROKEN_GEN2; +@@ -252,52 +277,60 @@ static int ceva_ahci_probe(struct platform_device *pdev) + if (of_property_read_u8_array(np, "ceva,p0-cominit-params", + (u8 *)&cevapriv->pp2c[0], 4) < 0) { + dev_warn(dev, "ceva,p0-cominit-params property not defined\n"); +- return -EINVAL; ++ rc = -EINVAL; ++ goto disable_resources; + } + + if (of_property_read_u8_array(np, "ceva,p1-cominit-params", + (u8 *)&cevapriv->pp2c[1], 4) < 0) { + dev_warn(dev, "ceva,p1-cominit-params property not defined\n"); +- return -EINVAL; ++ rc = -EINVAL; ++ goto disable_resources; + } + + /* Read OOB timing value for COMWAKE from device-tree*/ + if (of_property_read_u8_array(np, "ceva,p0-comwake-params", + (u8 *)&cevapriv->pp3c[0], 4) < 0) { + dev_warn(dev, "ceva,p0-comwake-params property not defined\n"); +- return -EINVAL; ++ rc = -EINVAL; ++ goto disable_resources; + } + + if (of_property_read_u8_array(np, "ceva,p1-comwake-params", + (u8 *)&cevapriv->pp3c[1], 4) < 0) { + dev_warn(dev, "ceva,p1-comwake-params property not defined\n"); +- return -EINVAL; ++ rc = -EINVAL; ++ goto disable_resources; + } + + /* Read phy BURST timing value from device-tree */ + if (of_property_read_u8_array(np, "ceva,p0-burst-params", + (u8 *)&cevapriv->pp4c[0], 4) < 0) { + dev_warn(dev, "ceva,p0-burst-params property not defined\n"); +- return -EINVAL; ++ rc = -EINVAL; ++ goto disable_resources; + } + + if (of_property_read_u8_array(np, "ceva,p1-burst-params", + (u8 *)&cevapriv->pp4c[1], 4) < 0) { + dev_warn(dev, "ceva,p1-burst-params property not defined\n"); +- return -EINVAL; ++ rc = -EINVAL; ++ goto disable_resources; + } + + /* Read phy RETRY interval timing value from device-tree */ + if (of_property_read_u16_array(np, "ceva,p0-retry-params", + (u16 *)&cevapriv->pp5c[0], 2) < 0) { + dev_warn(dev, "ceva,p0-retry-params property not defined\n"); +- return -EINVAL; ++ rc = -EINVAL; ++ goto disable_resources; + } + + if (of_property_read_u16_array(np, "ceva,p1-retry-params", + (u16 *)&cevapriv->pp5c[1], 2) < 0) { + dev_warn(dev, "ceva,p1-retry-params property not defined\n"); +- return -EINVAL; ++ rc = -EINVAL; ++ goto disable_resources; + } + + /* +@@ -335,7 +368,7 @@ static int __maybe_unused ceva_ahci_resume(struct device *dev) + struct ahci_host_priv *hpriv = host->private_data; + int rc; + +- rc = ahci_platform_enable_resources(hpriv); ++ rc = ceva_ahci_platform_enable_resources(hpriv); + if (rc) + return rc; + +diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c +index 09ed67772fae4..be3412cdb22e7 100644 +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -2001,6 +2001,33 @@ bool ata_dev_power_init_tf(struct ata_device *dev, struct ata_taskfile *tf, + return true; + } + ++static bool ata_dev_power_is_active(struct ata_device *dev) ++{ ++ struct ata_taskfile tf; ++ unsigned int err_mask; ++ ++ ata_tf_init(dev, &tf); ++ tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR; ++ tf.protocol = ATA_PROT_NODATA; ++ tf.command = ATA_CMD_CHK_POWER; ++ ++ err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); ++ if (err_mask) { ++ ata_dev_err(dev, "Check power mode failed (err_mask=0x%x)\n", ++ err_mask); ++ /* ++ * Assume we are in standby mode so that we always force a ++ * spinup in ata_dev_power_set_active(). ++ */ ++ return false; ++ } ++ ++ ata_dev_dbg(dev, "Power mode: 0x%02x\n", tf.nsect); ++ ++ /* Active or idle */ ++ return tf.nsect == 0xff; ++} ++ + /** + * ata_dev_power_set_standby - Set a device power mode to standby + * @dev: target device +@@ -2017,6 +2044,11 @@ void ata_dev_power_set_standby(struct ata_device *dev) + struct ata_taskfile tf; + unsigned int err_mask; + ++ /* If the device is already sleeping or in standby, do nothing. */ ++ if ((dev->flags & ATA_DFLAG_SLEEPING) || ++ !ata_dev_power_is_active(dev)) ++ return; ++ + /* + * Some odd clown BIOSes issue spindown on power off (ACPI S4 or S5) + * causing some drives to spin up and down again. For these, do nothing +@@ -2042,33 +2074,6 @@ void ata_dev_power_set_standby(struct ata_device *dev) + err_mask); + } + +-static bool ata_dev_power_is_active(struct ata_device *dev) +-{ +- struct ata_taskfile tf; +- unsigned int err_mask; +- +- ata_tf_init(dev, &tf); +- tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR; +- tf.protocol = ATA_PROT_NODATA; +- tf.command = ATA_CMD_CHK_POWER; +- +- err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); +- if (err_mask) { +- ata_dev_err(dev, "Check power mode failed (err_mask=0x%x)\n", +- err_mask); +- /* +- * Assume we are in standby mode so that we always force a +- * spinup in ata_dev_power_set_active(). +- */ +- return false; +- } +- +- ata_dev_dbg(dev, "Power mode: 0x%02x\n", tf.nsect); +- +- /* Active or idle */ +- return tf.nsect == 0xff; +-} +- + /** + * ata_dev_power_set_active - Set a device power mode to active + * @dev: target device +diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c +index cf6883756155a..37eff1c974515 100644 +--- a/drivers/block/aoe/aoeblk.c ++++ b/drivers/block/aoe/aoeblk.c +@@ -333,6 +333,7 @@ aoeblk_gdalloc(void *vp) + struct gendisk *gd; + mempool_t *mp; + struct blk_mq_tag_set *set; ++ sector_t ssize; + ulong flags; + int late = 0; + int err; +@@ -395,7 +396,7 @@ aoeblk_gdalloc(void *vp) + gd->minors = AOE_PARTITIONS; + gd->fops = &aoe_bdops; + gd->private_data = d; +- set_capacity(gd, d->ssize); ++ ssize = d->ssize; + snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d", + d->aoemajor, d->aoeminor); + +@@ -404,6 +405,8 @@ aoeblk_gdalloc(void *vp) + + spin_unlock_irqrestore(&d->lock, flags); + ++ set_capacity(gd, ssize); ++ + err = device_add_disk(NULL, gd, aoe_attr_groups); + if (err) + goto out_disk_cleanup; +diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c +index 47556d8ccc320..2c846eed5a2af 100644 +--- a/drivers/block/virtio_blk.c ++++ b/drivers/block/virtio_blk.c +@@ -1627,14 +1627,15 @@ static int virtblk_freeze(struct virtio_device *vdev) + { + struct virtio_blk *vblk = vdev->priv; + ++ /* Ensure no requests in virtqueues before deleting vqs. */ ++ blk_mq_freeze_queue(vblk->disk->queue); ++ + /* Ensure we don't receive any more interrupts */ + virtio_reset_device(vdev); + + /* Make sure no work handler is accessing the device. */ + flush_work(&vblk->config_work); + +- blk_mq_quiesce_queue(vblk->disk->queue); +- + vdev->config->del_vqs(vdev); + kfree(vblk->vqs); + +@@ -1652,7 +1653,7 @@ static int virtblk_restore(struct virtio_device *vdev) + + virtio_device_ready(vdev); + +- blk_mq_unquiesce_queue(vblk->disk->queue); ++ blk_mq_unfreeze_queue(vblk->disk->queue); + return 0; + } + #endif +diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c +index 42c9386a7b423..f9fd1582f150d 100644 +--- a/drivers/bus/imx-weim.c ++++ b/drivers/bus/imx-weim.c +@@ -117,7 +117,7 @@ static int imx_weim_gpr_setup(struct platform_device *pdev) + i++; + } + +- if (i == 0 || i % 4) ++ if (i == 0) + goto err; + + for (i = 0; i < ARRAY_SIZE(gprvals); i++) { +diff --git a/drivers/cache/ax45mp_cache.c b/drivers/cache/ax45mp_cache.c +index 57186c58dc849..1d7dd3d2c101c 100644 +--- a/drivers/cache/ax45mp_cache.c ++++ b/drivers/cache/ax45mp_cache.c +@@ -129,8 +129,12 @@ static void ax45mp_dma_cache_wback(phys_addr_t paddr, size_t size) + unsigned long line_size; + unsigned long flags; + ++ if (unlikely(start == end)) ++ return; ++ + line_size = ax45mp_priv.ax45mp_cache_line_size; + start = start & (~(line_size - 1)); ++ end = ((end + line_size - 1) & (~(line_size - 1))); + local_irq_save(flags); + ax45mp_cpu_dcache_wb_range(start, end); + local_irq_restore(flags); +diff --git a/drivers/crypto/virtio/virtio_crypto_akcipher_algs.c b/drivers/crypto/virtio/virtio_crypto_akcipher_algs.c +index 2621ff8a93764..de53eddf6796b 100644 +--- a/drivers/crypto/virtio/virtio_crypto_akcipher_algs.c ++++ b/drivers/crypto/virtio/virtio_crypto_akcipher_algs.c +@@ -104,7 +104,8 @@ static void virtio_crypto_dataq_akcipher_callback(struct virtio_crypto_request * + } + + static int virtio_crypto_alg_akcipher_init_session(struct virtio_crypto_akcipher_ctx *ctx, +- struct virtio_crypto_ctrl_header *header, void *para, ++ struct virtio_crypto_ctrl_header *header, ++ struct virtio_crypto_akcipher_session_para *para, + const uint8_t *key, unsigned int keylen) + { + struct scatterlist outhdr_sg, key_sg, inhdr_sg, *sgs[3]; +@@ -128,7 +129,7 @@ static int virtio_crypto_alg_akcipher_init_session(struct virtio_crypto_akcipher + + ctrl = &vc_ctrl_req->ctrl; + memcpy(&ctrl->header, header, sizeof(ctrl->header)); +- memcpy(&ctrl->u, para, sizeof(ctrl->u)); ++ memcpy(&ctrl->u.akcipher_create_session.para, para, sizeof(*para)); + input = &vc_ctrl_req->input; + input->status = cpu_to_le32(VIRTIO_CRYPTO_ERR); + +diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c +index 2034eb4ce83fb..b3cec89126b24 100644 +--- a/drivers/cxl/acpi.c ++++ b/drivers/cxl/acpi.c +@@ -194,31 +194,27 @@ struct cxl_cfmws_context { + int id; + }; + +-static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg, +- const unsigned long end) ++static int __cxl_parse_cfmws(struct acpi_cedt_cfmws *cfmws, ++ struct cxl_cfmws_context *ctx) + { + int target_map[CXL_DECODER_MAX_INTERLEAVE]; +- struct cxl_cfmws_context *ctx = arg; + struct cxl_port *root_port = ctx->root_port; + struct resource *cxl_res = ctx->cxl_res; + struct cxl_cxims_context cxims_ctx; + struct cxl_root_decoder *cxlrd; + struct device *dev = ctx->dev; +- struct acpi_cedt_cfmws *cfmws; + cxl_calc_hb_fn cxl_calc_hb; + struct cxl_decoder *cxld; + unsigned int ways, i, ig; + struct resource *res; + int rc; + +- cfmws = (struct acpi_cedt_cfmws *) header; +- + rc = cxl_acpi_cfmws_verify(dev, cfmws); + if (rc) { + dev_err(dev, "CFMWS range %#llx-%#llx not registered\n", + cfmws->base_hpa, + cfmws->base_hpa + cfmws->window_size - 1); +- return 0; ++ return rc; + } + + rc = eiw_to_ways(cfmws->interleave_ways, &ways); +@@ -254,7 +250,7 @@ static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg, + + cxlrd = cxl_root_decoder_alloc(root_port, ways, cxl_calc_hb); + if (IS_ERR(cxlrd)) +- return 0; ++ return PTR_ERR(cxlrd); + + cxld = &cxlrd->cxlsd.cxld; + cxld->flags = cfmws_to_decoder_flags(cfmws->restrictions); +@@ -298,16 +294,7 @@ static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg, + put_device(&cxld->dev); + else + rc = cxl_decoder_autoremove(dev, cxld); +- if (rc) { +- dev_err(dev, "Failed to add decode range: %pr", res); +- return rc; +- } +- dev_dbg(dev, "add: %s node: %d range [%#llx - %#llx]\n", +- dev_name(&cxld->dev), +- phys_to_target_node(cxld->hpa_range.start), +- cxld->hpa_range.start, cxld->hpa_range.end); +- +- return 0; ++ return rc; + + err_insert: + kfree(res->name); +@@ -316,6 +303,29 @@ static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg, + return -ENOMEM; + } + ++static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg, ++ const unsigned long end) ++{ ++ struct acpi_cedt_cfmws *cfmws = (struct acpi_cedt_cfmws *)header; ++ struct cxl_cfmws_context *ctx = arg; ++ struct device *dev = ctx->dev; ++ int rc; ++ ++ rc = __cxl_parse_cfmws(cfmws, ctx); ++ if (rc) ++ dev_err(dev, ++ "Failed to add decode range: [%#llx - %#llx] (%d)\n", ++ cfmws->base_hpa, ++ cfmws->base_hpa + cfmws->window_size - 1, rc); ++ else ++ dev_dbg(dev, "decode range: node: %d range [%#llx - %#llx]\n", ++ phys_to_target_node(cfmws->base_hpa), cfmws->base_hpa, ++ cfmws->base_hpa + cfmws->window_size - 1); ++ ++ /* never fail cxl_acpi load for a single window failure */ ++ return 0; ++} ++ + __mock struct acpi_device *to_cxl_host_bridge(struct device *host, + struct device *dev) + { +diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c +index 37e1652afbc7e..deae3289de844 100644 +--- a/drivers/cxl/core/pci.c ++++ b/drivers/cxl/core/pci.c +@@ -476,9 +476,9 @@ int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm, + allowed++; + } + +- if (!allowed) { +- cxl_set_mem_enable(cxlds, 0); +- info->mem_enabled = 0; ++ if (!allowed && info->mem_enabled) { ++ dev_err(dev, "Range register decodes outside platform defined CXL ranges.\n"); ++ return -ENXIO; + } + + /* +@@ -931,11 +931,21 @@ static void cxl_handle_rdport_errors(struct cxl_dev_state *cxlds) { } + void cxl_cor_error_detected(struct pci_dev *pdev) + { + struct cxl_dev_state *cxlds = pci_get_drvdata(pdev); ++ struct device *dev = &cxlds->cxlmd->dev; ++ ++ scoped_guard(device, dev) { ++ if (!dev->driver) { ++ dev_warn(&pdev->dev, ++ "%s: memdev disabled, abort error handling\n", ++ dev_name(dev)); ++ return; ++ } + +- if (cxlds->rcd) +- cxl_handle_rdport_errors(cxlds); ++ if (cxlds->rcd) ++ cxl_handle_rdport_errors(cxlds); + +- cxl_handle_endpoint_cor_ras(cxlds); ++ cxl_handle_endpoint_cor_ras(cxlds); ++ } + } + EXPORT_SYMBOL_NS_GPL(cxl_cor_error_detected, CXL); + +@@ -947,16 +957,25 @@ pci_ers_result_t cxl_error_detected(struct pci_dev *pdev, + struct device *dev = &cxlmd->dev; + bool ue; + +- if (cxlds->rcd) +- cxl_handle_rdport_errors(cxlds); ++ scoped_guard(device, dev) { ++ if (!dev->driver) { ++ dev_warn(&pdev->dev, ++ "%s: memdev disabled, abort error handling\n", ++ dev_name(dev)); ++ return PCI_ERS_RESULT_DISCONNECT; ++ } ++ ++ if (cxlds->rcd) ++ cxl_handle_rdport_errors(cxlds); ++ /* ++ * A frozen channel indicates an impending reset which is fatal to ++ * CXL.mem operation, and will likely crash the system. On the off ++ * chance the situation is recoverable dump the status of the RAS ++ * capability registers and bounce the active state of the memdev. ++ */ ++ ue = cxl_handle_endpoint_ras(cxlds); ++ } + +- /* +- * A frozen channel indicates an impending reset which is fatal to +- * CXL.mem operation, and will likely crash the system. On the off +- * chance the situation is recoverable dump the status of the RAS +- * capability registers and bounce the active state of the memdev. +- */ +- ue = cxl_handle_endpoint_ras(cxlds); + + switch (state) { + case pci_channel_io_normal: +diff --git a/drivers/dma/apple-admac.c b/drivers/dma/apple-admac.c +index 5b63996640d9d..9588773dd2eb6 100644 +--- a/drivers/dma/apple-admac.c ++++ b/drivers/dma/apple-admac.c +@@ -57,6 +57,8 @@ + + #define REG_BUS_WIDTH(ch) (0x8040 + (ch) * 0x200) + ++#define BUS_WIDTH_WORD_SIZE GENMASK(3, 0) ++#define BUS_WIDTH_FRAME_SIZE GENMASK(7, 4) + #define BUS_WIDTH_8BIT 0x00 + #define BUS_WIDTH_16BIT 0x01 + #define BUS_WIDTH_32BIT 0x02 +@@ -740,7 +742,8 @@ static int admac_device_config(struct dma_chan *chan, + struct admac_data *ad = adchan->host; + bool is_tx = admac_chan_direction(adchan->no) == DMA_MEM_TO_DEV; + int wordsize = 0; +- u32 bus_width = 0; ++ u32 bus_width = readl_relaxed(ad->base + REG_BUS_WIDTH(adchan->no)) & ++ ~(BUS_WIDTH_WORD_SIZE | BUS_WIDTH_FRAME_SIZE); + + switch (is_tx ? config->dst_addr_width : config->src_addr_width) { + case DMA_SLAVE_BUSWIDTH_1_BYTE: +diff --git a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c +index 0745d9e7d259b..406f169b09a75 100644 +--- a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c ++++ b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c +@@ -176,7 +176,7 @@ dw_edma_debugfs_regs_wr(struct dw_edma *dw, struct dentry *dent) + }; + struct dentry *regs_dent, *ch_dent; + int nr_entries, i; +- char name[16]; ++ char name[32]; + + regs_dent = debugfs_create_dir(WRITE_STR, dent); + +@@ -239,7 +239,7 @@ static noinline_for_stack void dw_edma_debugfs_regs_rd(struct dw_edma *dw, + }; + struct dentry *regs_dent, *ch_dent; + int nr_entries, i; +- char name[16]; ++ char name[32]; + + regs_dent = debugfs_create_dir(READ_STR, dent); + +diff --git a/drivers/dma/dw-edma/dw-hdma-v0-debugfs.c b/drivers/dma/dw-edma/dw-hdma-v0-debugfs.c +index 520c81978b085..dcdc57fe976c1 100644 +--- a/drivers/dma/dw-edma/dw-hdma-v0-debugfs.c ++++ b/drivers/dma/dw-edma/dw-hdma-v0-debugfs.c +@@ -116,7 +116,7 @@ static void dw_hdma_debugfs_regs_ch(struct dw_edma *dw, enum dw_edma_dir dir, + static void dw_hdma_debugfs_regs_wr(struct dw_edma *dw, struct dentry *dent) + { + struct dentry *regs_dent, *ch_dent; +- char name[16]; ++ char name[32]; + int i; + + regs_dent = debugfs_create_dir(WRITE_STR, dent); +@@ -133,7 +133,7 @@ static void dw_hdma_debugfs_regs_wr(struct dw_edma *dw, struct dentry *dent) + static void dw_hdma_debugfs_regs_rd(struct dw_edma *dw, struct dentry *dent) + { + struct dentry *regs_dent, *ch_dent; +- char name[16]; ++ char name[32]; + int i; + + regs_dent = debugfs_create_dir(READ_STR, dent); +diff --git a/drivers/dma/fsl-qdma.c b/drivers/dma/fsl-qdma.c +index 3a5595a1d4421..9b141369bea5d 100644 +--- a/drivers/dma/fsl-qdma.c ++++ b/drivers/dma/fsl-qdma.c +@@ -805,7 +805,7 @@ fsl_qdma_irq_init(struct platform_device *pdev, + int i; + int cpu; + int ret; +- char irq_name[20]; ++ char irq_name[32]; + + fsl_qdma->error_irq = + platform_get_irq_byname(pdev, "qdma-error"); +diff --git a/drivers/dma/sh/shdma.h b/drivers/dma/sh/shdma.h +index 9c121a4b33ad8..f97d80343aea4 100644 +--- a/drivers/dma/sh/shdma.h ++++ b/drivers/dma/sh/shdma.h +@@ -25,7 +25,7 @@ struct sh_dmae_chan { + const struct sh_dmae_slave_config *config; /* Slave DMA configuration */ + int xmit_shift; /* log_2(bytes_per_xfer) */ + void __iomem *base; +- char dev_id[16]; /* unique name per DMAC of channel */ ++ char dev_id[32]; /* unique name per DMAC of channel */ + int pm_error; + dma_addr_t slave_addr; + }; +diff --git a/drivers/dma/ti/edma.c b/drivers/dma/ti/edma.c +index f1f920861fa9d..5f8d2e93ff3fb 100644 +--- a/drivers/dma/ti/edma.c ++++ b/drivers/dma/ti/edma.c +@@ -2404,6 +2404,11 @@ static int edma_probe(struct platform_device *pdev) + if (irq > 0) { + irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s_ccint", + dev_name(dev)); ++ if (!irq_name) { ++ ret = -ENOMEM; ++ goto err_disable_pm; ++ } ++ + ret = devm_request_irq(dev, irq, dma_irq_handler, 0, irq_name, + ecc); + if (ret) { +@@ -2420,6 +2425,11 @@ static int edma_probe(struct platform_device *pdev) + if (irq > 0) { + irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s_ccerrint", + dev_name(dev)); ++ if (!irq_name) { ++ ret = -ENOMEM; ++ goto err_disable_pm; ++ } ++ + ret = devm_request_irq(dev, irq, dma_ccerr_handler, 0, irq_name, + ecc); + if (ret) { +diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c +index 6ac5ff20a2fe2..8aaa7fcb2630d 100644 +--- a/drivers/firewire/core-card.c ++++ b/drivers/firewire/core-card.c +@@ -429,7 +429,23 @@ static void bm_work(struct work_struct *work) + */ + card->bm_generation = generation; + +- if (root_device == NULL) { ++ if (card->gap_count == 0) { ++ /* ++ * If self IDs have inconsistent gap counts, do a ++ * bus reset ASAP. The config rom read might never ++ * complete, so don't wait for it. However, still ++ * send a PHY configuration packet prior to the ++ * bus reset. The PHY configuration packet might ++ * fail, but 1394-2008 8.4.5.2 explicitly permits ++ * it in this case, so it should be safe to try. ++ */ ++ new_root_id = local_id; ++ /* ++ * We must always send a bus reset if the gap count ++ * is inconsistent, so bypass the 5-reset limit. ++ */ ++ card->bm_retries = 0; ++ } else if (root_device == NULL) { + /* + * Either link_on is false, or we failed to read the + * config rom. In either case, pick another root. +diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c +index 83f5bb57fa4c4..83092d93f36a6 100644 +--- a/drivers/firmware/efi/arm-runtime.c ++++ b/drivers/firmware/efi/arm-runtime.c +@@ -107,7 +107,7 @@ static int __init arm_enable_runtime_services(void) + efi_memory_desc_t *md; + + for_each_efi_memory_desc(md) { +- int md_size = md->num_pages << EFI_PAGE_SHIFT; ++ u64 md_size = md->num_pages << EFI_PAGE_SHIFT; + struct resource *res; + + if (!(md->attribute & EFI_MEMORY_SP)) +diff --git a/drivers/firmware/efi/efi-init.c b/drivers/firmware/efi/efi-init.c +index d4987d0130801..a00e07b853f22 100644 +--- a/drivers/firmware/efi/efi-init.c ++++ b/drivers/firmware/efi/efi-init.c +@@ -143,15 +143,6 @@ static __init int is_usable_memory(efi_memory_desc_t *md) + case EFI_BOOT_SERVICES_DATA: + case EFI_CONVENTIONAL_MEMORY: + case EFI_PERSISTENT_MEMORY: +- /* +- * Special purpose memory is 'soft reserved', which means it +- * is set aside initially, but can be hotplugged back in or +- * be assigned to the dax driver after boot. +- */ +- if (efi_soft_reserve_enabled() && +- (md->attribute & EFI_MEMORY_SP)) +- return false; +- + /* + * According to the spec, these regions are no longer reserved + * after calling ExitBootServices(). However, we can only use +@@ -196,6 +187,16 @@ static __init void reserve_regions(void) + size = npages << PAGE_SHIFT; + + if (is_memory(md)) { ++ /* ++ * Special purpose memory is 'soft reserved', which ++ * means it is set aside initially. Don't add a memblock ++ * for it now so that it can be hotplugged back in or ++ * be assigned to the dax driver after boot. ++ */ ++ if (efi_soft_reserve_enabled() && ++ (md->attribute & EFI_MEMORY_SP)) ++ continue; ++ + early_init_dt_add_memory_arch(paddr, size); + + if (!is_usable_memory(md)) +diff --git a/drivers/firmware/efi/riscv-runtime.c b/drivers/firmware/efi/riscv-runtime.c +index 09525fb5c240e..01f0f90ea4183 100644 +--- a/drivers/firmware/efi/riscv-runtime.c ++++ b/drivers/firmware/efi/riscv-runtime.c +@@ -85,7 +85,7 @@ static int __init riscv_enable_runtime_services(void) + efi_memory_desc_t *md; + + for_each_efi_memory_desc(md) { +- int md_size = md->num_pages << EFI_PAGE_SHIFT; ++ u64 md_size = md->num_pages << EFI_PAGE_SHIFT; + struct resource *res; + + if (!(md->attribute & EFI_MEMORY_SP)) +diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c +index 95d2a7b2ea3e2..15de124d5b402 100644 +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -2043,6 +2043,11 @@ EXPORT_SYMBOL_GPL(gpiochip_generic_free); + int gpiochip_generic_config(struct gpio_chip *gc, unsigned int offset, + unsigned long config) + { ++#ifdef CONFIG_PINCTRL ++ if (list_empty(&gc->gpiodev->pin_ranges)) ++ return -ENOTSUPP; ++#endif ++ + return pinctrl_gpio_set_config(gc, offset, config); + } + EXPORT_SYMBOL_GPL(gpiochip_generic_config); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +index 50f57d4dfd8ff..31d4b5a2c5e83 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +@@ -1041,6 +1041,8 @@ struct amdgpu_device { + bool in_s3; + bool in_s4; + bool in_s0ix; ++ /* indicate amdgpu suspension status */ ++ bool suspend_complete; + + enum pp_mp1_state mp1_state; + struct amdgpu_doorbell_index doorbell_index; +@@ -1509,9 +1511,11 @@ static inline int amdgpu_acpi_smart_shift_update(struct drm_device *dev, + #if defined(CONFIG_ACPI) && defined(CONFIG_SUSPEND) + bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev); + bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev); ++void amdgpu_choose_low_power_state(struct amdgpu_device *adev); + #else + static inline bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { return false; } + static inline bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev) { return false; } ++static inline void amdgpu_choose_low_power_state(struct amdgpu_device *adev) { } + #endif + + #if defined(CONFIG_DRM_AMD_DC) +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +index 2deebece810e7..7099ff9cf8c50 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +@@ -1519,4 +1519,22 @@ bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) + #endif /* CONFIG_AMD_PMC */ + } + ++/** ++ * amdgpu_choose_low_power_state ++ * ++ * @adev: amdgpu_device_pointer ++ * ++ * Choose the target low power state for the GPU ++ */ ++void amdgpu_choose_low_power_state(struct amdgpu_device *adev) ++{ ++ if (adev->in_runpm) ++ return; ++ ++ if (amdgpu_acpi_is_s0ix_active(adev)) ++ adev->in_s0ix = true; ++ else if (amdgpu_acpi_is_s3_active(adev)) ++ adev->in_s3 = true; ++} ++ + #endif /* CONFIG_SUSPEND */ +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index 19bc8d47317bb..7f48c7ec41366 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -4441,13 +4441,15 @@ int amdgpu_device_prepare(struct drm_device *dev) + struct amdgpu_device *adev = drm_to_adev(dev); + int i, r; + ++ amdgpu_choose_low_power_state(adev); ++ + if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) + return 0; + + /* Evict the majority of BOs before starting suspend sequence */ + r = amdgpu_device_evict_resources(adev); + if (r) +- return r; ++ goto unprepare; + + for (i = 0; i < adev->num_ip_blocks; i++) { + if (!adev->ip_blocks[i].status.valid) +@@ -4456,10 +4458,15 @@ int amdgpu_device_prepare(struct drm_device *dev) + continue; + r = adev->ip_blocks[i].version->funcs->prepare_suspend((void *)adev); + if (r) +- return r; ++ goto unprepare; + } + + return 0; ++ ++unprepare: ++ adev->in_s0ix = adev->in_s3 = false; ++ ++ return r; + } + + /** +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +index a7ad77ed09ca4..10c4a8cfa18a0 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +@@ -2449,6 +2449,7 @@ static int amdgpu_pmops_suspend(struct device *dev) + struct drm_device *drm_dev = dev_get_drvdata(dev); + struct amdgpu_device *adev = drm_to_adev(drm_dev); + ++ adev->suspend_complete = false; + if (amdgpu_acpi_is_s0ix_active(adev)) + adev->in_s0ix = true; + else if (amdgpu_acpi_is_s3_active(adev)) +@@ -2463,6 +2464,7 @@ static int amdgpu_pmops_suspend_noirq(struct device *dev) + struct drm_device *drm_dev = dev_get_drvdata(dev); + struct amdgpu_device *adev = drm_to_adev(drm_dev); + ++ adev->suspend_complete = true; + if (amdgpu_acpi_should_gpu_reset(adev)) + return amdgpu_asic_reset(adev); + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c +index 468a67b302d4c..ca5c86e5f7cd6 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c +@@ -362,7 +362,7 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size + } + } + +- if (copy_to_user((char *)buf, context->mem_context.shared_buf, shared_buf_len)) ++ if (copy_to_user((char *)&buf[copy_pos], context->mem_context.shared_buf, shared_buf_len)) + ret = -EFAULT; + + err_free_shared_buf: +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +index 69c5009107460..3bc6943365a4f 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +@@ -3034,6 +3034,14 @@ static int gfx_v9_0_cp_gfx_start(struct amdgpu_device *adev) + + gfx_v9_0_cp_gfx_enable(adev, true); + ++ /* Now only limit the quirk on the APU gfx9 series and already ++ * confirmed that the APU gfx10/gfx11 needn't such update. ++ */ ++ if (adev->flags & AMD_IS_APU && ++ adev->in_s3 && !adev->suspend_complete) { ++ DRM_INFO(" Will skip the CSB packet resubmit\n"); ++ return 0; ++ } + r = amdgpu_ring_alloc(ring, gfx_v9_0_get_csb_size(adev) + 4 + 3); + if (r) { + DRM_ERROR("amdgpu: cp failed to lock ring (%d).\n", r); +diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c +index 25a3da83e0fb9..db013f86147a1 100644 +--- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c ++++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c +@@ -431,6 +431,12 @@ static void nbio_v7_9_init_registers(struct amdgpu_device *adev) + u32 inst_mask; + int i; + ++ if (amdgpu_sriov_vf(adev)) ++ adev->rmmio_remap.reg_offset = ++ SOC15_REG_OFFSET( ++ NBIO, 0, ++ regBIF_BX_DEV0_EPF0_VF0_HDP_MEM_COHERENCY_FLUSH_CNTL) ++ << 2; + WREG32_SOC15(NBIO, 0, regXCC_DOORBELL_FENCE, + 0xff & ~(adev->gfx.xcc_mask)); + +diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c +index 51342809af034..9b5af3f1383a7 100644 +--- a/drivers/gpu/drm/amd/amdgpu/soc15.c ++++ b/drivers/gpu/drm/amd/amdgpu/soc15.c +@@ -1297,10 +1297,32 @@ static int soc15_common_suspend(void *handle) + return soc15_common_hw_fini(adev); + } + ++static bool soc15_need_reset_on_resume(struct amdgpu_device *adev) ++{ ++ u32 sol_reg; ++ ++ sol_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81); ++ ++ /* Will reset for the following suspend abort cases. ++ * 1) Only reset limit on APU side, dGPU hasn't checked yet. ++ * 2) S3 suspend abort and TOS already launched. ++ */ ++ if (adev->flags & AMD_IS_APU && adev->in_s3 && ++ !adev->suspend_complete && ++ sol_reg) ++ return true; ++ ++ return false; ++} ++ + static int soc15_common_resume(void *handle) + { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + ++ if (soc15_need_reset_on_resume(adev)) { ++ dev_info(adev->dev, "S3 suspend abort case, let's reset ASIC.\n"); ++ soc15_asic_reset(adev); ++ } + return soc15_common_hw_init(adev); + } + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +index 28162bfbe1b33..71445ab63b5e5 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +@@ -1482,10 +1482,15 @@ void kfd_dec_compute_active(struct kfd_node *dev); + + /* Cgroup Support */ + /* Check with device cgroup if @kfd device is accessible */ +-static inline int kfd_devcgroup_check_permission(struct kfd_node *kfd) ++static inline int kfd_devcgroup_check_permission(struct kfd_node *node) + { + #if defined(CONFIG_CGROUP_DEVICE) || defined(CONFIG_CGROUP_BPF) +- struct drm_device *ddev = adev_to_drm(kfd->adev); ++ struct drm_device *ddev; ++ ++ if (node->xcp) ++ ddev = node->xcp->ddev; ++ else ++ ddev = adev_to_drm(node->adev); + + return devcgroup_check_permission(DEVCG_DEV_CHAR, DRM_MAJOR, + ddev->render->index, +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index d3d1ccf66ece0..272c27495ede6 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -1810,21 +1810,12 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) + DRM_ERROR("amdgpu: fail to register dmub aux callback"); + goto error; + } +- if (!register_dmub_notify_callback(adev, DMUB_NOTIFICATION_HPD, dmub_hpd_callback, true)) { +- DRM_ERROR("amdgpu: fail to register dmub hpd callback"); +- goto error; +- } +- if (!register_dmub_notify_callback(adev, DMUB_NOTIFICATION_HPD_IRQ, dmub_hpd_callback, true)) { +- DRM_ERROR("amdgpu: fail to register dmub hpd callback"); +- goto error; +- } +- } +- +- /* Enable outbox notification only after IRQ handlers are registered and DMUB is alive. +- * It is expected that DMUB will resend any pending notifications at this point, for +- * example HPD from DPIA. +- */ +- if (dc_is_dmub_outbox_supported(adev->dm.dc)) { ++ /* Enable outbox notification only after IRQ handlers are registered and DMUB is alive. ++ * It is expected that DMUB will resend any pending notifications at this point. Note ++ * that hpd and hpd_irq handler registration are deferred to register_hpd_handlers() to ++ * align legacy interface initialization sequence. Connection status will be proactivly ++ * detected once in the amdgpu_dm_initialize_drm_device. ++ */ + dc_enable_dmub_outbox(adev->dm.dc); + + /* DPIA trace goes to dmesg logs only if outbox is enabled */ +@@ -2254,6 +2245,7 @@ static int dm_sw_fini(void *handle) + + if (adev->dm.dmub_srv) { + dmub_srv_destroy(adev->dm.dmub_srv); ++ kfree(adev->dm.dmub_srv); + adev->dm.dmub_srv = NULL; + } + +@@ -3494,6 +3486,14 @@ static void register_hpd_handlers(struct amdgpu_device *adev) + int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT; + int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT; + ++ if (dc_is_dmub_outbox_supported(adev->dm.dc)) { ++ if (!register_dmub_notify_callback(adev, DMUB_NOTIFICATION_HPD, dmub_hpd_callback, true)) ++ DRM_ERROR("amdgpu: fail to register dmub hpd callback"); ++ ++ if (!register_dmub_notify_callback(adev, DMUB_NOTIFICATION_HPD_IRQ, dmub_hpd_callback, true)) ++ DRM_ERROR("amdgpu: fail to register dmub hpd callback"); ++ } ++ + list_for_each_entry(connector, + &dev->mode_config.connector_list, head) { + +@@ -3519,10 +3519,6 @@ static void register_hpd_handlers(struct amdgpu_device *adev) + handle_hpd_rx_irq, + (void *) aconnector); + } +- +- if (adev->dm.hpd_rx_offload_wq) +- adev->dm.hpd_rx_offload_wq[connector->index].aconnector = +- aconnector; + } + } + +@@ -4493,6 +4489,10 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) + + link = dc_get_link_at_index(dm->dc, i); + ++ if (dm->hpd_rx_offload_wq) ++ dm->hpd_rx_offload_wq[aconnector->base.index].aconnector = ++ aconnector; ++ + if (!dc_link_detect_connection_type(link, &new_connection_type)) + DRM_ERROR("KMS: Failed to detect connector\n"); + +@@ -6445,10 +6445,15 @@ amdgpu_dm_connector_late_register(struct drm_connector *connector) + static void amdgpu_dm_connector_funcs_force(struct drm_connector *connector) + { + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); +- struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); + struct dc_link *dc_link = aconnector->dc_link; + struct dc_sink *dc_em_sink = aconnector->dc_em_sink; + struct edid *edid; ++ struct i2c_adapter *ddc; ++ ++ if (dc_link->aux_mode) ++ ddc = &aconnector->dm_dp_aux.aux.ddc; ++ else ++ ddc = &aconnector->i2c->base; + + /* + * Note: drm_get_edid gets edid in the following order: +@@ -6456,7 +6461,7 @@ static void amdgpu_dm_connector_funcs_force(struct drm_connector *connector) + * 2) firmware EDID if set via edid_firmware module parameter + * 3) regular DDC read. + */ +- edid = drm_get_edid(connector, &amdgpu_connector->ddc_bus->aux.ddc); ++ edid = drm_get_edid(connector, ddc); + if (!edid) { + DRM_ERROR("No EDID found on connector: %s.\n", connector->name); + return; +@@ -6497,12 +6502,18 @@ static int get_modes(struct drm_connector *connector) + static void create_eml_sink(struct amdgpu_dm_connector *aconnector) + { + struct drm_connector *connector = &aconnector->base; +- struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(&aconnector->base); ++ struct dc_link *dc_link = aconnector->dc_link; + struct dc_sink_init_data init_params = { + .link = aconnector->dc_link, + .sink_signal = SIGNAL_TYPE_VIRTUAL + }; + struct edid *edid; ++ struct i2c_adapter *ddc; ++ ++ if (dc_link->aux_mode) ++ ddc = &aconnector->dm_dp_aux.aux.ddc; ++ else ++ ddc = &aconnector->i2c->base; + + /* + * Note: drm_get_edid gets edid in the following order: +@@ -6510,7 +6521,7 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector) + * 2) firmware EDID if set via edid_firmware module parameter + * 3) regular DDC read. + */ +- edid = drm_get_edid(connector, &amdgpu_connector->ddc_bus->aux.ddc); ++ edid = drm_get_edid(connector, ddc); + if (!edid) { + DRM_ERROR("No EDID found on connector: %s.\n", connector->name); + return; +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +index 51467f132c260..d595030c3359e 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +@@ -711,7 +711,7 @@ static inline int dm_irq_state(struct amdgpu_device *adev, + { + bool st; + enum dc_irq_source irq_source; +- ++ struct dc *dc = adev->dm.dc; + struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc_id]; + + if (!acrtc) { +@@ -729,6 +729,9 @@ static inline int dm_irq_state(struct amdgpu_device *adev, + + st = (state == AMDGPU_IRQ_STATE_ENABLE); + ++ if (dc && dc->caps.ips_support && dc->idle_optimizations_allowed) ++ dc_allow_idle_optimizations(dc, false); ++ + dc_interrupt_set(adev->dm.dc, irq_source, st); + return 0; + } +diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +index b5b29451d2db8..bc7a375f43c0c 100644 +--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c ++++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +@@ -1850,19 +1850,21 @@ static enum bp_result get_firmware_info_v3_2( + /* Vega12 */ + smu_info_v3_2 = GET_IMAGE(struct atom_smu_info_v3_2, + DATA_TABLES(smu_info)); +- DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_2->gpuclk_ss_percentage); + if (!smu_info_v3_2) + return BP_RESULT_BADBIOSTABLE; + ++ DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_2->gpuclk_ss_percentage); ++ + info->default_engine_clk = smu_info_v3_2->bootup_dcefclk_10khz * 10; + } else if (revision.minor == 3) { + /* Vega20 */ + smu_info_v3_3 = GET_IMAGE(struct atom_smu_info_v3_3, + DATA_TABLES(smu_info)); +- DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_3->gpuclk_ss_percentage); + if (!smu_info_v3_3) + return BP_RESULT_BADBIOSTABLE; + ++ DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_3->gpuclk_ss_percentage); ++ + info->default_engine_clk = smu_info_v3_3->bootup_dcefclk_10khz * 10; + } + +@@ -2423,10 +2425,11 @@ static enum bp_result get_integrated_info_v11( + info_v11 = GET_IMAGE(struct atom_integrated_system_info_v1_11, + DATA_TABLES(integratedsysteminfo)); + +- DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v11->gpuclk_ss_percentage); + if (info_v11 == NULL) + return BP_RESULT_BADBIOSTABLE; + ++ DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v11->gpuclk_ss_percentage); ++ + info->gpu_cap_info = + le32_to_cpu(info_v11->gpucapinfo); + /* +@@ -2638,11 +2641,12 @@ static enum bp_result get_integrated_info_v2_1( + + info_v2_1 = GET_IMAGE(struct atom_integrated_system_info_v2_1, + DATA_TABLES(integratedsysteminfo)); +- DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_1->gpuclk_ss_percentage); + + if (info_v2_1 == NULL) + return BP_RESULT_BADBIOSTABLE; + ++ DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_1->gpuclk_ss_percentage); ++ + info->gpu_cap_info = + le32_to_cpu(info_v2_1->gpucapinfo); + /* +@@ -2800,11 +2804,11 @@ static enum bp_result get_integrated_info_v2_2( + info_v2_2 = GET_IMAGE(struct atom_integrated_system_info_v2_2, + DATA_TABLES(integratedsysteminfo)); + +- DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_2->gpuclk_ss_percentage); +- + if (info_v2_2 == NULL) + return BP_RESULT_BADBIOSTABLE; + ++ DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_2->gpuclk_ss_percentage); ++ + info->gpu_cap_info = + le32_to_cpu(info_v2_2->gpucapinfo); + /* +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c +index ed94187c2afa2..f365773d57148 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c +@@ -497,7 +497,7 @@ void dc_link_enable_hpd_filter(struct dc_link *link, bool enable) + link->dc->link_srv->enable_hpd_filter(link, enable); + } + +-bool dc_link_validate(struct dc *dc, const struct dc_stream_state *streams, const unsigned int count) ++bool dc_link_dp_dpia_validate(struct dc *dc, const struct dc_stream_state *streams, const unsigned int count) + { + return dc->link_srv->validate_dpia_bandwidth(streams, count); + } +diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h +index 2cafd644baff8..8164a534048c4 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc.h ++++ b/drivers/gpu/drm/amd/display/dc/dc.h +@@ -2187,11 +2187,11 @@ int dc_link_dp_dpia_handle_usb4_bandwidth_allocation_for_link( + * + * @dc: pointer to dc struct + * @stream: pointer to all possible streams +- * @num_streams: number of valid DPIA streams ++ * @count: number of valid DPIA streams + * + * return: TRUE if bw used by DPIAs doesn't exceed available BW else return FALSE + */ +-bool dc_link_validate(struct dc *dc, const struct dc_stream_state *streams, ++bool dc_link_dp_dpia_validate(struct dc *dc, const struct dc_stream_state *streams, + const unsigned int count); + + /* Sink Interfaces - A sink corresponds to a display output device */ +diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +index 61d1b4eadbee3..05b3433cbb0b4 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c ++++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +@@ -124,7 +124,7 @@ bool dc_dmub_srv_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_srv, + unsigned int count, + union dmub_rb_cmd *cmd_list) + { +- struct dc_context *dc_ctx = dc_dmub_srv->ctx; ++ struct dc_context *dc_ctx; + struct dmub_srv *dmub; + enum dmub_status status; + int i; +@@ -132,6 +132,7 @@ bool dc_dmub_srv_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_srv, + if (!dc_dmub_srv || !dc_dmub_srv->dmub) + return false; + ++ dc_ctx = dc_dmub_srv->ctx; + dmub = dc_dmub_srv->dmub; + + for (i = 0 ; i < count; i++) { +@@ -1129,7 +1130,7 @@ void dc_dmub_srv_subvp_save_surf_addr(const struct dc_dmub_srv *dc_dmub_srv, con + + bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait) + { +- struct dc_context *dc_ctx = dc_dmub_srv->ctx; ++ struct dc_context *dc_ctx; + enum dmub_status status; + + if (!dc_dmub_srv || !dc_dmub_srv->dmub) +@@ -1138,6 +1139,8 @@ bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait) + if (dc_dmub_srv->ctx->dc->debug.dmcub_emulation) + return true; + ++ dc_ctx = dc_dmub_srv->ctx; ++ + if (wait) { + status = dmub_srv_wait_for_hw_pwr_up(dc_dmub_srv->dmub, 500000); + if (status != DMUB_STATUS_OK) { +diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +index eeeeeef4d7173..1cb7765f593aa 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +@@ -1377,6 +1377,12 @@ struct dp_trace { + #ifndef DP_TUNNELING_STATUS + #define DP_TUNNELING_STATUS 0xE0025 /* 1.4a */ + #endif ++#ifndef DP_TUNNELING_MAX_LINK_RATE ++#define DP_TUNNELING_MAX_LINK_RATE 0xE0028 /* 1.4a */ ++#endif ++#ifndef DP_TUNNELING_MAX_LANE_COUNT ++#define DP_TUNNELING_MAX_LANE_COUNT 0xE0029 /* 1.4a */ ++#endif + #ifndef DPTX_BW_ALLOCATION_MODE_CONTROL + #define DPTX_BW_ALLOCATION_MODE_CONTROL 0xE0030 /* 1.4a */ + #endif +diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h +index 35d146217aef0..66d0774bef527 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_types.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_types.h +@@ -1100,21 +1100,25 @@ struct dc_panel_config { + } ilr; + }; + ++#define MAX_SINKS_PER_LINK 4 ++ + /* + * USB4 DPIA BW ALLOCATION STRUCTS + */ + struct dc_dpia_bw_alloc { +- int sink_verified_bw; // The Verified BW that sink can allocated and use that has been verified already +- int sink_allocated_bw; // The Actual Allocated BW that sink currently allocated +- int sink_max_bw; // The Max BW that sink can require/support ++ int remote_sink_req_bw[MAX_SINKS_PER_LINK]; // BW requested by remote sinks ++ int link_verified_bw; // The Verified BW that link can allocated and use that has been verified already ++ int link_max_bw; // The Max BW that link can require/support ++ int allocated_bw; // The Actual Allocated BW for this DPIA + int estimated_bw; // The estimated available BW for this DPIA + int bw_granularity; // BW Granularity ++ int dp_overhead; // DP overhead in dp tunneling + bool bw_alloc_enabled; // The BW Alloc Mode Support is turned ON for all 3: DP-Tx & Dpia & CM + bool response_ready; // Response ready from the CM side ++ uint8_t nrd_max_lane_count; // Non-reduced max lane count ++ uint8_t nrd_max_link_rate; // Non-reduced max link rate + }; + +-#define MAX_SINKS_PER_LINK 4 +- + enum dc_hpd_enable_select { + HPD_EN_FOR_ALL_EDP = 0, + HPD_EN_FOR_PRIMARY_EDP_ONLY, +diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c +index e8570060d007b..5bca67407c5b1 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c ++++ b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c +@@ -290,4 +290,5 @@ void dce_panel_cntl_construct( + dce_panel_cntl->base.funcs = &dce_link_panel_cntl_funcs; + dce_panel_cntl->base.ctx = init_data->ctx; + dce_panel_cntl->base.inst = init_data->inst; ++ dce_panel_cntl->base.pwrseq_inst = 0; + } +diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_panel_cntl.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_panel_cntl.c +index ad0df1a72a90a..9e96a3ace2077 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_panel_cntl.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_panel_cntl.c +@@ -215,4 +215,5 @@ void dcn301_panel_cntl_construct( + dcn301_panel_cntl->base.funcs = &dcn301_link_panel_cntl_funcs; + dcn301_panel_cntl->base.ctx = init_data->ctx; + dcn301_panel_cntl->base.inst = init_data->inst; ++ dcn301_panel_cntl->base.pwrseq_inst = 0; + } +diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c +index 03248422d6ffd..281be20b1a107 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c +@@ -154,8 +154,24 @@ void dcn31_panel_cntl_construct( + struct dcn31_panel_cntl *dcn31_panel_cntl, + const struct panel_cntl_init_data *init_data) + { ++ uint8_t pwrseq_inst = 0xF; ++ + dcn31_panel_cntl->base.funcs = &dcn31_link_panel_cntl_funcs; + dcn31_panel_cntl->base.ctx = init_data->ctx; + dcn31_panel_cntl->base.inst = init_data->inst; +- dcn31_panel_cntl->base.pwrseq_inst = init_data->pwrseq_inst; ++ ++ switch (init_data->eng_id) { ++ case ENGINE_ID_DIGA: ++ pwrseq_inst = 0; ++ break; ++ case ENGINE_ID_DIGB: ++ pwrseq_inst = 1; ++ break; ++ default: ++ DC_LOG_WARNING("Unsupported pwrseq engine id: %d!\n", init_data->eng_id); ++ ASSERT(false); ++ break; ++ } ++ ++ dcn31_panel_cntl->base.pwrseq_inst = pwrseq_inst; + } +diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c +index 501388014855c..d761b0df28784 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c +@@ -203,12 +203,12 @@ void dcn32_link_encoder_construct( + enc10->base.hpd_source = init_data->hpd_source; + enc10->base.connector = init_data->connector; + +- if (enc10->base.connector.id == CONNECTOR_ID_USBC) +- enc10->base.features.flags.bits.DP_IS_USB_C = 1; + + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; + + enc10->base.features = *enc_features; ++ if (enc10->base.connector.id == CONNECTOR_ID_USBC) ++ enc10->base.features.flags.bits.DP_IS_USB_C = 1; + + enc10->base.transmitter = init_data->transmitter; + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c +index da94e5309fbaf..81e349d5835bb 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c +@@ -184,8 +184,6 @@ void dcn35_link_encoder_construct( + enc10->base.hpd_source = init_data->hpd_source; + enc10->base.connector = init_data->connector; + +- if (enc10->base.connector.id == CONNECTOR_ID_USBC) +- enc10->base.features.flags.bits.DP_IS_USB_C = 1; + + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; + +@@ -240,6 +238,8 @@ void dcn35_link_encoder_construct( + } + + enc10->base.features.flags.bits.HDMI_6GB_EN = 1; ++ if (enc10->base.connector.id == CONNECTOR_ID_USBC) ++ enc10->base.features.flags.bits.DP_IS_USB_C = 1; + + if (bp_funcs->get_connector_speed_cap_info) + result = bp_funcs->get_connector_speed_cap_info(enc10->base.ctx->dc_bios, +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +index 9fedf99475695..c1f1665e553d6 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +@@ -1182,9 +1182,9 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) + dto_params.timing = &pipe_ctx->stream->timing; + dp_hpo_inst = pipe_ctx->stream_res.hpo_dp_stream_enc->inst; + if (dccg) { +- dccg->funcs->set_dtbclk_dto(dccg, &dto_params); + dccg->funcs->disable_symclk32_se(dccg, dp_hpo_inst); + dccg->funcs->set_dpstreamclk(dccg, REFCLK, tg->inst, dp_hpo_inst); ++ dccg->funcs->set_dtbclk_dto(dccg, &dto_params); + } + } else if (dccg && dccg->funcs->disable_symclk_se) { + dccg->funcs->disable_symclk_se(dccg, stream_enc->stream_enc_inst, +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +index da0181fef411f..c966f38583cb9 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +@@ -2776,18 +2776,17 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) + } + + if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { +- dp_hpo_inst = pipe_ctx->stream_res.hpo_dp_stream_enc->inst; +- dccg->funcs->set_dpstreamclk(dccg, DTBCLK0, tg->inst, dp_hpo_inst); +- +- phyd32clk = get_phyd32clk_src(link); +- dccg->funcs->enable_symclk32_se(dccg, dp_hpo_inst, phyd32clk); +- + dto_params.otg_inst = tg->inst; + dto_params.pixclk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10; + dto_params.num_odm_segments = get_odm_segment_count(pipe_ctx); + dto_params.timing = &pipe_ctx->stream->timing; + dto_params.ref_dtbclk_khz = dc->clk_mgr->funcs->get_dtb_ref_clk_frequency(dc->clk_mgr); + dccg->funcs->set_dtbclk_dto(dccg, &dto_params); ++ dp_hpo_inst = pipe_ctx->stream_res.hpo_dp_stream_enc->inst; ++ dccg->funcs->set_dpstreamclk(dccg, DTBCLK0, tg->inst, dp_hpo_inst); ++ ++ phyd32clk = get_phyd32clk_src(link); ++ dccg->funcs->enable_symclk32_se(dccg, dp_hpo_inst, phyd32clk); + } else { + if (dccg->funcs->enable_symclk_se) + dccg->funcs->enable_symclk_se(dccg, stream_enc->stream_enc_inst, +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h b/drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h +index 248adc1705e35..660897e12a9ce 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h +@@ -56,7 +56,7 @@ struct panel_cntl_funcs { + struct panel_cntl_init_data { + struct dc_context *ctx; + uint32_t inst; +- uint32_t pwrseq_inst; ++ uint32_t eng_id; + }; + + struct panel_cntl { +diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +index a08ae59c1ea9f..007ee32c202e8 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c ++++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +@@ -2098,17 +2098,11 @@ static enum dc_status enable_link_dp(struct dc_state *state, + } + } + +- /* +- * If the link is DP-over-USB4 do the following: +- * - Train with fallback when enabling DPIA link. Conventional links are ++ /* Train with fallback when enabling DPIA link. Conventional links are + * trained with fallback during sink detection. +- * - Allocate only what the stream needs for bw in Gbps. Inform the CM +- * in case stream needs more or less bw from what has been allocated +- * earlier at plug time. + */ +- if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) { ++ if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) + do_fallback = true; +- } + + /* + * Temporary w/a to get DP2.0 link rates to work with SST. +@@ -2290,6 +2284,32 @@ static enum dc_status enable_link( + return status; + } + ++static bool allocate_usb4_bandwidth_for_stream(struct dc_stream_state *stream, int bw) ++{ ++ return true; ++} ++ ++static bool allocate_usb4_bandwidth(struct dc_stream_state *stream) ++{ ++ bool ret; ++ ++ int bw = dc_bandwidth_in_kbps_from_timing(&stream->timing, ++ dc_link_get_highest_encoding_format(stream->sink->link)); ++ ++ ret = allocate_usb4_bandwidth_for_stream(stream, bw); ++ ++ return ret; ++} ++ ++static bool deallocate_usb4_bandwidth(struct dc_stream_state *stream) ++{ ++ bool ret; ++ ++ ret = allocate_usb4_bandwidth_for_stream(stream, 0); ++ ++ return ret; ++} ++ + void link_set_dpms_off(struct pipe_ctx *pipe_ctx) + { + struct dc *dc = pipe_ctx->stream->ctx->dc; +@@ -2325,6 +2345,9 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx) + update_psp_stream_config(pipe_ctx, true); + dc->hwss.blank_stream(pipe_ctx); + ++ if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) ++ deallocate_usb4_bandwidth(pipe_ctx->stream); ++ + if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) + deallocate_mst_payload(pipe_ctx); + else if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT && +@@ -2567,6 +2590,9 @@ void link_set_dpms_on( + } + } + ++ if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) ++ allocate_usb4_bandwidth(pipe_ctx->stream); ++ + if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) + allocate_mst_payload(pipe_ctx); + else if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT && +diff --git a/drivers/gpu/drm/amd/display/dc/link/link_factory.c b/drivers/gpu/drm/amd/display/dc/link/link_factory.c +index ff7801aa552a4..41f8230f942bd 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/link_factory.c ++++ b/drivers/gpu/drm/amd/display/dc/link/link_factory.c +@@ -368,30 +368,6 @@ static enum transmitter translate_encoder_to_transmitter( + } + } + +-static uint8_t translate_dig_inst_to_pwrseq_inst(struct dc_link *link) +-{ +- uint8_t pwrseq_inst = 0xF; +- struct dc_context *dc_ctx = link->dc->ctx; +- +- DC_LOGGER_INIT(dc_ctx->logger); +- +- switch (link->eng_id) { +- case ENGINE_ID_DIGA: +- pwrseq_inst = 0; +- break; +- case ENGINE_ID_DIGB: +- pwrseq_inst = 1; +- break; +- default: +- DC_LOG_WARNING("Unsupported pwrseq engine id: %d!\n", link->eng_id); +- ASSERT(false); +- break; +- } +- +- return pwrseq_inst; +-} +- +- + static void link_destruct(struct dc_link *link) + { + int i; +@@ -655,7 +631,7 @@ static bool construct_phy(struct dc_link *link, + link->link_id.id == CONNECTOR_ID_LVDS)) { + panel_cntl_init_data.ctx = dc_ctx; + panel_cntl_init_data.inst = panel_cntl_init_data.ctx->dc_edp_id_count; +- panel_cntl_init_data.pwrseq_inst = translate_dig_inst_to_pwrseq_inst(link); ++ panel_cntl_init_data.eng_id = link->eng_id; + link->panel_cntl = + link->dc->res_pool->funcs->panel_cntl_create( + &panel_cntl_init_data); +diff --git a/drivers/gpu/drm/amd/display/dc/link/link_validation.c b/drivers/gpu/drm/amd/display/dc/link/link_validation.c +index b45fda96eaf64..5b0bc7f6a188c 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/link_validation.c ++++ b/drivers/gpu/drm/amd/display/dc/link/link_validation.c +@@ -346,23 +346,61 @@ enum dc_status link_validate_mode_timing( + return DC_OK; + } + ++/* ++ * This function calculates the bandwidth required for the stream timing ++ * and aggregates the stream bandwidth for the respective dpia link ++ * ++ * @stream: pointer to the dc_stream_state struct instance ++ * @num_streams: number of streams to be validated ++ * ++ * return: true if validation is succeeded ++ */ + bool link_validate_dpia_bandwidth(const struct dc_stream_state *stream, const unsigned int num_streams) + { +- bool ret = true; +- int bw_needed[MAX_DPIA_NUM]; +- struct dc_link *link[MAX_DPIA_NUM]; ++ int bw_needed[MAX_DPIA_NUM] = {0}; ++ struct dc_link *dpia_link[MAX_DPIA_NUM] = {0}; ++ int num_dpias = 0; ++ ++ for (unsigned int i = 0; i < num_streams; ++i) { ++ if (stream[i].signal == SIGNAL_TYPE_DISPLAY_PORT) { ++ /* new dpia sst stream, check whether it exceeds max dpia */ ++ if (num_dpias >= MAX_DPIA_NUM) ++ return false; + +- if (!num_streams || num_streams > MAX_DPIA_NUM) +- return ret; ++ dpia_link[num_dpias] = stream[i].link; ++ bw_needed[num_dpias] = dc_bandwidth_in_kbps_from_timing(&stream[i].timing, ++ dc_link_get_highest_encoding_format(dpia_link[num_dpias])); ++ num_dpias++; ++ } else if (stream[i].signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { ++ uint8_t j = 0; ++ /* check whether its a known dpia link */ ++ for (; j < num_dpias; ++j) { ++ if (dpia_link[j] == stream[i].link) ++ break; ++ } ++ ++ if (j == num_dpias) { ++ /* new dpia mst stream, check whether it exceeds max dpia */ ++ if (num_dpias >= MAX_DPIA_NUM) ++ return false; ++ else { ++ dpia_link[j] = stream[i].link; ++ num_dpias++; ++ } ++ } ++ ++ bw_needed[j] += dc_bandwidth_in_kbps_from_timing(&stream[i].timing, ++ dc_link_get_highest_encoding_format(dpia_link[j])); ++ } ++ } + +- for (uint8_t i = 0; i < num_streams; ++i) { ++ /* Include dp overheads */ ++ for (uint8_t i = 0; i < num_dpias; ++i) { ++ int dp_overhead = 0; + +- link[i] = stream[i].link; +- bw_needed[i] = dc_bandwidth_in_kbps_from_timing(&stream[i].timing, +- dc_link_get_highest_encoding_format(link[i])); ++ dp_overhead = link_dp_dpia_get_dp_overhead_in_dp_tunneling(dpia_link[i]); ++ bw_needed[i] += dp_overhead; + } + +- ret = dpia_validate_usb4_bw(link, bw_needed, num_streams); +- +- return ret; ++ return dpia_validate_usb4_bw(dpia_link, bw_needed, num_dpias); + } +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c +index d6e1f969bfd52..5491b707cec88 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c +@@ -54,11 +54,18 @@ static bool get_bw_alloc_proceed_flag(struct dc_link *tmp) + static void reset_bw_alloc_struct(struct dc_link *link) + { + link->dpia_bw_alloc_config.bw_alloc_enabled = false; +- link->dpia_bw_alloc_config.sink_verified_bw = 0; +- link->dpia_bw_alloc_config.sink_max_bw = 0; ++ link->dpia_bw_alloc_config.link_verified_bw = 0; ++ link->dpia_bw_alloc_config.link_max_bw = 0; ++ link->dpia_bw_alloc_config.allocated_bw = 0; + link->dpia_bw_alloc_config.estimated_bw = 0; + link->dpia_bw_alloc_config.bw_granularity = 0; ++ link->dpia_bw_alloc_config.dp_overhead = 0; + link->dpia_bw_alloc_config.response_ready = false; ++ link->dpia_bw_alloc_config.nrd_max_lane_count = 0; ++ link->dpia_bw_alloc_config.nrd_max_link_rate = 0; ++ for (int i = 0; i < MAX_SINKS_PER_LINK; i++) ++ link->dpia_bw_alloc_config.remote_sink_req_bw[i] = 0; ++ DC_LOG_DEBUG("reset usb4 bw alloc of link(%d)\n", link->link_index); + } + + #define BW_GRANULARITY_0 4 // 0.25 Gbps +@@ -104,6 +111,32 @@ static int get_estimated_bw(struct dc_link *link) + return bw_estimated_bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity); + } + ++static int get_non_reduced_max_link_rate(struct dc_link *link) ++{ ++ uint8_t nrd_max_link_rate = 0; ++ ++ core_link_read_dpcd( ++ link, ++ DP_TUNNELING_MAX_LINK_RATE, ++ &nrd_max_link_rate, ++ sizeof(uint8_t)); ++ ++ return nrd_max_link_rate; ++} ++ ++static int get_non_reduced_max_lane_count(struct dc_link *link) ++{ ++ uint8_t nrd_max_lane_count = 0; ++ ++ core_link_read_dpcd( ++ link, ++ DP_TUNNELING_MAX_LANE_COUNT, ++ &nrd_max_lane_count, ++ sizeof(uint8_t)); ++ ++ return nrd_max_lane_count; ++} ++ + /* + * Read all New BW alloc configuration ex: estimated_bw, allocated_bw, + * granuality, Driver_ID, CM_Group, & populate the BW allocation structs +@@ -111,13 +144,20 @@ static int get_estimated_bw(struct dc_link *link) + */ + static void init_usb4_bw_struct(struct dc_link *link) + { +- // Init the known values ++ reset_bw_alloc_struct(link); ++ ++ /* init the known values */ + link->dpia_bw_alloc_config.bw_granularity = get_bw_granularity(link); + link->dpia_bw_alloc_config.estimated_bw = get_estimated_bw(link); ++ link->dpia_bw_alloc_config.nrd_max_link_rate = get_non_reduced_max_link_rate(link); ++ link->dpia_bw_alloc_config.nrd_max_lane_count = get_non_reduced_max_lane_count(link); + + DC_LOG_DEBUG("%s: bw_granularity(%d), estimated_bw(%d)\n", + __func__, link->dpia_bw_alloc_config.bw_granularity, + link->dpia_bw_alloc_config.estimated_bw); ++ DC_LOG_DEBUG("%s: nrd_max_link_rate(%d), nrd_max_lane_count(%d)\n", ++ __func__, link->dpia_bw_alloc_config.nrd_max_link_rate, ++ link->dpia_bw_alloc_config.nrd_max_lane_count); + } + + static uint8_t get_lowest_dpia_index(struct dc_link *link) +@@ -142,39 +182,50 @@ static uint8_t get_lowest_dpia_index(struct dc_link *link) + } + + /* +- * Get the Max Available BW or Max Estimated BW for each Host Router ++ * Get the maximum dp tunnel banwidth of host router + * +- * @link: pointer to the dc_link struct instance +- * @type: ESTIMATD BW or MAX AVAILABLE BW ++ * @dc: pointer to the dc struct instance ++ * @hr_index: host router index + * +- * return: response_ready flag from dc_link struct ++ * return: host router maximum dp tunnel bandwidth + */ +-static int get_host_router_total_bw(struct dc_link *link, uint8_t type) ++static int get_host_router_total_dp_tunnel_bw(const struct dc *dc, uint8_t hr_index) + { +- const struct dc *dc_struct = link->dc; +- uint8_t lowest_dpia_index = get_lowest_dpia_index(link); +- uint8_t idx = (link->link_index - lowest_dpia_index) / 2, idx_temp = 0; +- struct dc_link *link_temp; ++ uint8_t lowest_dpia_index = get_lowest_dpia_index(dc->links[0]); ++ uint8_t hr_index_temp = 0; ++ struct dc_link *link_dpia_primary, *link_dpia_secondary; + int total_bw = 0; +- int i; + +- for (i = 0; i < MAX_PIPES * 2; ++i) { ++ for (uint8_t i = 0; i < (MAX_PIPES * 2) - 1; ++i) { + +- if (!dc_struct->links[i] || dc_struct->links[i]->ep_type != DISPLAY_ENDPOINT_USB4_DPIA) ++ if (!dc->links[i] || dc->links[i]->ep_type != DISPLAY_ENDPOINT_USB4_DPIA) + continue; + +- link_temp = dc_struct->links[i]; +- if (!link_temp || !link_temp->hpd_status) +- continue; +- +- idx_temp = (link_temp->link_index - lowest_dpia_index) / 2; +- +- if (idx_temp == idx) { +- +- if (type == HOST_ROUTER_BW_ESTIMATED) +- total_bw += link_temp->dpia_bw_alloc_config.estimated_bw; +- else if (type == HOST_ROUTER_BW_ALLOCATED) +- total_bw += link_temp->dpia_bw_alloc_config.sink_allocated_bw; ++ hr_index_temp = (dc->links[i]->link_index - lowest_dpia_index) / 2; ++ ++ if (hr_index_temp == hr_index) { ++ link_dpia_primary = dc->links[i]; ++ link_dpia_secondary = dc->links[i + 1]; ++ ++ /** ++ * If BW allocation enabled on both DPIAs, then ++ * HR BW = Estimated(dpia_primary) + Allocated(dpia_secondary) ++ * otherwise HR BW = Estimated(bw alloc enabled dpia) ++ */ ++ if ((link_dpia_primary->hpd_status && ++ link_dpia_primary->dpia_bw_alloc_config.bw_alloc_enabled) && ++ (link_dpia_secondary->hpd_status && ++ link_dpia_secondary->dpia_bw_alloc_config.bw_alloc_enabled)) { ++ total_bw += link_dpia_primary->dpia_bw_alloc_config.estimated_bw + ++ link_dpia_secondary->dpia_bw_alloc_config.allocated_bw; ++ } else if (link_dpia_primary->hpd_status && ++ link_dpia_primary->dpia_bw_alloc_config.bw_alloc_enabled) { ++ total_bw = link_dpia_primary->dpia_bw_alloc_config.estimated_bw; ++ } else if (link_dpia_secondary->hpd_status && ++ link_dpia_secondary->dpia_bw_alloc_config.bw_alloc_enabled) { ++ total_bw += link_dpia_secondary->dpia_bw_alloc_config.estimated_bw; ++ } ++ break; + } + } + +@@ -194,7 +245,6 @@ static void dpia_bw_alloc_unplug(struct dc_link *link) + if (link) { + DC_LOG_DEBUG("%s: resetting bw alloc config for link(%d)\n", + __func__, link->link_index); +- link->dpia_bw_alloc_config.sink_allocated_bw = 0; + reset_bw_alloc_struct(link); + } + } +@@ -220,7 +270,7 @@ static void set_usb4_req_bw_req(struct dc_link *link, int req_bw) + + /* Error check whether requested and allocated are equal */ + req_bw = requested_bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity); +- if (req_bw == link->dpia_bw_alloc_config.sink_allocated_bw) { ++ if (req_bw == link->dpia_bw_alloc_config.allocated_bw) { + DC_LOG_ERROR("%s: Request bw equals to allocated bw for link(%d)\n", + __func__, link->link_index); + } +@@ -343,9 +393,9 @@ void dpia_handle_bw_alloc_response(struct dc_link *link, uint8_t bw, uint8_t res + DC_LOG_DEBUG("%s: BW REQ SUCCESS for DP-TX Request for link(%d)\n", + __func__, link->link_index); + DC_LOG_DEBUG("%s: current allocated_bw(%d), new allocated_bw(%d)\n", +- __func__, link->dpia_bw_alloc_config.sink_allocated_bw, bw_needed); ++ __func__, link->dpia_bw_alloc_config.allocated_bw, bw_needed); + +- link->dpia_bw_alloc_config.sink_allocated_bw = bw_needed; ++ link->dpia_bw_alloc_config.allocated_bw = bw_needed; + + link->dpia_bw_alloc_config.response_ready = true; + break; +@@ -383,8 +433,8 @@ int dpia_handle_usb4_bandwidth_allocation_for_link(struct dc_link *link, int pea + if (link->hpd_status && peak_bw > 0) { + + // If DP over USB4 then we need to check BW allocation +- link->dpia_bw_alloc_config.sink_max_bw = peak_bw; +- set_usb4_req_bw_req(link, link->dpia_bw_alloc_config.sink_max_bw); ++ link->dpia_bw_alloc_config.link_max_bw = peak_bw; ++ set_usb4_req_bw_req(link, link->dpia_bw_alloc_config.link_max_bw); + + do { + if (timeout > 0) +@@ -396,8 +446,8 @@ int dpia_handle_usb4_bandwidth_allocation_for_link(struct dc_link *link, int pea + + if (!timeout) + ret = 0;// ERROR TIMEOUT waiting for response for allocating bw +- else if (link->dpia_bw_alloc_config.sink_allocated_bw > 0) +- ret = get_host_router_total_bw(link, HOST_ROUTER_BW_ALLOCATED); ++ else if (link->dpia_bw_alloc_config.allocated_bw > 0) ++ ret = link->dpia_bw_alloc_config.allocated_bw; + } + //2. Cold Unplug + else if (!link->hpd_status) +@@ -406,7 +456,6 @@ int dpia_handle_usb4_bandwidth_allocation_for_link(struct dc_link *link, int pea + out: + return ret; + } +- + bool link_dp_dpia_allocate_usb4_bandwidth_for_stream(struct dc_link *link, int req_bw) + { + bool ret = false; +@@ -414,7 +463,7 @@ bool link_dp_dpia_allocate_usb4_bandwidth_for_stream(struct dc_link *link, int r + + DC_LOG_DEBUG("%s: ENTER: link(%d), hpd_status(%d), current allocated_bw(%d), req_bw(%d)\n", + __func__, link->link_index, link->hpd_status, +- link->dpia_bw_alloc_config.sink_allocated_bw, req_bw); ++ link->dpia_bw_alloc_config.allocated_bw, req_bw); + + if (!get_bw_alloc_proceed_flag(link)) + goto out; +@@ -439,31 +488,70 @@ bool link_dp_dpia_allocate_usb4_bandwidth_for_stream(struct dc_link *link, int r + bool dpia_validate_usb4_bw(struct dc_link **link, int *bw_needed_per_dpia, const unsigned int num_dpias) + { + bool ret = true; +- int bw_needed_per_hr[MAX_HR_NUM] = { 0, 0 }; +- uint8_t lowest_dpia_index = 0, dpia_index = 0; +- uint8_t i; ++ int bw_needed_per_hr[MAX_HR_NUM] = { 0, 0 }, host_router_total_dp_bw = 0; ++ uint8_t lowest_dpia_index, i, hr_index; + + if (!num_dpias || num_dpias > MAX_DPIA_NUM) + return ret; + +- //Get total Host Router BW & Validate against each Host Router max BW ++ lowest_dpia_index = get_lowest_dpia_index(link[0]); ++ ++ /* get total Host Router BW with granularity for the given modes */ + for (i = 0; i < num_dpias; ++i) { ++ int granularity_Gbps = 0; ++ int bw_granularity = 0; + + if (!link[i]->dpia_bw_alloc_config.bw_alloc_enabled) + continue; + +- lowest_dpia_index = get_lowest_dpia_index(link[i]); + if (link[i]->link_index < lowest_dpia_index) + continue; + +- dpia_index = (link[i]->link_index - lowest_dpia_index) / 2; +- bw_needed_per_hr[dpia_index] += bw_needed_per_dpia[i]; +- if (bw_needed_per_hr[dpia_index] > get_host_router_total_bw(link[i], HOST_ROUTER_BW_ALLOCATED)) { ++ granularity_Gbps = (Kbps_TO_Gbps / link[i]->dpia_bw_alloc_config.bw_granularity); ++ bw_granularity = (bw_needed_per_dpia[i] / granularity_Gbps) * granularity_Gbps + ++ ((bw_needed_per_dpia[i] % granularity_Gbps) ? granularity_Gbps : 0); + +- ret = false; +- break; ++ hr_index = (link[i]->link_index - lowest_dpia_index) / 2; ++ bw_needed_per_hr[hr_index] += bw_granularity; ++ } ++ ++ /* validate against each Host Router max BW */ ++ for (hr_index = 0; hr_index < MAX_HR_NUM; ++hr_index) { ++ if (bw_needed_per_hr[hr_index]) { ++ host_router_total_dp_bw = get_host_router_total_dp_tunnel_bw(link[0]->dc, hr_index); ++ if (bw_needed_per_hr[hr_index] > host_router_total_dp_bw) { ++ ret = false; ++ break; ++ } + } + } + + return ret; + } ++ ++int link_dp_dpia_get_dp_overhead_in_dp_tunneling(struct dc_link *link) ++{ ++ int dp_overhead = 0, link_mst_overhead = 0; ++ ++ if (!get_bw_alloc_proceed_flag((link))) ++ return dp_overhead; ++ ++ /* if its mst link, add MTPH overhead */ ++ if ((link->type == dc_connection_mst_branch) && ++ !link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) { ++ /* For 8b/10b encoding: MTP is 64 time slots long, slot 0 is used for MTPH ++ * MST overhead is 1/64 of link bandwidth (excluding any overhead) ++ */ ++ const struct dc_link_settings *link_cap = ++ dc_link_get_link_cap(link); ++ uint32_t link_bw_in_kbps = (uint32_t)link_cap->link_rate * ++ (uint32_t)link_cap->lane_count * ++ LINK_RATE_REF_FREQ_IN_KHZ * 8; ++ link_mst_overhead = (link_bw_in_kbps / 64) + ((link_bw_in_kbps % 64) ? 1 : 0); ++ } ++ ++ /* add all the overheads */ ++ dp_overhead = link_mst_overhead; ++ ++ return dp_overhead; ++} +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.h +index 981bc4eb6120e..3b6d8494f9d5d 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.h ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.h +@@ -99,4 +99,13 @@ void dpia_handle_bw_alloc_response(struct dc_link *link, uint8_t bw, uint8_t res + */ + bool dpia_validate_usb4_bw(struct dc_link **link, int *bw_needed, const unsigned int num_dpias); + ++/* ++ * Obtain all the DP overheads in dp tunneling for the dpia link ++ * ++ * @link: pointer to the dc_link struct instance ++ * ++ * return: DP overheads in DP tunneling ++ */ ++int link_dp_dpia_get_dp_overhead_in_dp_tunneling(struct dc_link *link); ++ + #endif /* DC_INC_LINK_DP_DPIA_BW_H_ */ +diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c +index c1a99bf4dffd1..c4222b886db7c 100644 +--- a/drivers/gpu/drm/drm_buddy.c ++++ b/drivers/gpu/drm/drm_buddy.c +@@ -538,13 +538,13 @@ static int __alloc_range(struct drm_buddy *mm, + list_add(&block->left->tmp_link, dfs); + } while (1); + +- list_splice_tail(&allocated, blocks); +- + if (total_allocated < size) { + err = -ENOSPC; + goto err_free; + } + ++ list_splice_tail(&allocated, blocks); ++ + return 0; + + err_undo: +diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c +index 01da6789d0440..5860428da8de8 100644 +--- a/drivers/gpu/drm/drm_syncobj.c ++++ b/drivers/gpu/drm/drm_syncobj.c +@@ -1034,7 +1034,8 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs, + uint64_t *points; + uint32_t signaled_count, i; + +- if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) ++ if (flags & (DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT | ++ DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE)) + lockdep_assert_none_held_once(); + + points = kmalloc_array(count, sizeof(*points), GFP_KERNEL); +@@ -1103,7 +1104,8 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs, + * fallthough and try a 0 timeout wait! + */ + +- if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) { ++ if (flags & (DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT | ++ DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE)) { + for (i = 0; i < count; ++i) + drm_syncobj_fence_add_wait(syncobjs[i], &entries[i]); + } +@@ -1378,10 +1380,21 @@ syncobj_eventfd_entry_func(struct drm_syncobj *syncobj, + + /* This happens inside the syncobj lock */ + fence = dma_fence_get(rcu_dereference_protected(syncobj->fence, 1)); ++ if (!fence) ++ return; ++ + ret = dma_fence_chain_find_seqno(&fence, entry->point); +- if (ret != 0 || !fence) { ++ if (ret != 0) { ++ /* The given seqno has not been submitted yet. */ + dma_fence_put(fence); + return; ++ } else if (!fence) { ++ /* If dma_fence_chain_find_seqno returns 0 but sets the fence ++ * to NULL, it implies that the given seqno is signaled and a ++ * later seqno has already been submitted. Assign a stub fence ++ * so that the eventfd still gets signaled below. ++ */ ++ fence = dma_fence_get_stub(); + } + + list_del_init(&entry->node); +diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c +index a9ac7d45d1f33..312f88d90af95 100644 +--- a/drivers/gpu/drm/i915/display/intel_sdvo.c ++++ b/drivers/gpu/drm/i915/display/intel_sdvo.c +@@ -1208,7 +1208,7 @@ static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo, + struct intel_sdvo_tv_format format; + u32 format_map; + +- format_map = 1 << conn_state->tv.mode; ++ format_map = 1 << conn_state->tv.legacy_mode; + memset(&format, 0, sizeof(format)); + memcpy(&format, &format_map, min(sizeof(format), sizeof(format_map))); + +@@ -2288,7 +2288,7 @@ static int intel_sdvo_get_tv_modes(struct drm_connector *connector) + * Read the list of supported input resolutions for the selected TV + * format. + */ +- format_map = 1 << conn_state->tv.mode; ++ format_map = 1 << conn_state->tv.legacy_mode; + memcpy(&tv_res, &format_map, + min(sizeof(format_map), sizeof(struct intel_sdvo_sdtv_resolution_request))); + +@@ -2353,7 +2353,7 @@ intel_sdvo_connector_atomic_get_property(struct drm_connector *connector, + int i; + + for (i = 0; i < intel_sdvo_connector->format_supported_num; i++) +- if (state->tv.mode == intel_sdvo_connector->tv_format_supported[i]) { ++ if (state->tv.legacy_mode == intel_sdvo_connector->tv_format_supported[i]) { + *val = i; + + return 0; +@@ -2409,7 +2409,7 @@ intel_sdvo_connector_atomic_set_property(struct drm_connector *connector, + struct intel_sdvo_connector_state *sdvo_state = to_intel_sdvo_connector_state(state); + + if (property == intel_sdvo_connector->tv_format) { +- state->tv.mode = intel_sdvo_connector->tv_format_supported[val]; ++ state->tv.legacy_mode = intel_sdvo_connector->tv_format_supported[val]; + + if (state->crtc) { + struct drm_crtc_state *crtc_state = +@@ -3066,7 +3066,7 @@ static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo, + drm_property_add_enum(intel_sdvo_connector->tv_format, i, + tv_format_names[intel_sdvo_connector->tv_format_supported[i]]); + +- intel_sdvo_connector->base.base.state->tv.mode = intel_sdvo_connector->tv_format_supported[0]; ++ intel_sdvo_connector->base.base.state->tv.legacy_mode = intel_sdvo_connector->tv_format_supported[0]; + drm_object_attach_property(&intel_sdvo_connector->base.base.base, + intel_sdvo_connector->tv_format, 0); + return true; +diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c +index 2ee4f0d958513..f790fd10ba00a 100644 +--- a/drivers/gpu/drm/i915/display/intel_tv.c ++++ b/drivers/gpu/drm/i915/display/intel_tv.c +@@ -949,7 +949,7 @@ intel_disable_tv(struct intel_atomic_state *state, + + static const struct tv_mode *intel_tv_mode_find(const struct drm_connector_state *conn_state) + { +- int format = conn_state->tv.mode; ++ int format = conn_state->tv.legacy_mode; + + return &tv_modes[format]; + } +@@ -1710,7 +1710,7 @@ static void intel_tv_find_better_format(struct drm_connector *connector) + break; + } + +- connector->state->tv.mode = i; ++ connector->state->tv.legacy_mode = i; + } + + static int +@@ -1865,7 +1865,7 @@ static int intel_tv_atomic_check(struct drm_connector *connector, + old_state = drm_atomic_get_old_connector_state(state, connector); + new_crtc_state = drm_atomic_get_new_crtc_state(state, new_state->crtc); + +- if (old_state->tv.mode != new_state->tv.mode || ++ if (old_state->tv.legacy_mode != new_state->tv.legacy_mode || + old_state->tv.margins.left != new_state->tv.margins.left || + old_state->tv.margins.right != new_state->tv.margins.right || + old_state->tv.margins.top != new_state->tv.margins.top || +@@ -1902,7 +1902,7 @@ static void intel_tv_add_properties(struct drm_connector *connector) + conn_state->tv.margins.right = 46; + conn_state->tv.margins.bottom = 37; + +- conn_state->tv.mode = 0; ++ conn_state->tv.legacy_mode = 0; + + /* Create TV properties then attach current values */ + for (i = 0; i < ARRAY_SIZE(tv_modes); i++) { +@@ -1916,7 +1916,7 @@ static void intel_tv_add_properties(struct drm_connector *connector) + + drm_object_attach_property(&connector->base, + i915->drm.mode_config.legacy_tv_mode_property, +- conn_state->tv.mode); ++ conn_state->tv.legacy_mode); + drm_object_attach_property(&connector->base, + i915->drm.mode_config.tv_left_margin_property, + conn_state->tv.margins.left); +diff --git a/drivers/gpu/drm/meson/meson_encoder_cvbs.c b/drivers/gpu/drm/meson/meson_encoder_cvbs.c +index 3f73b211fa8e3..3407450435e20 100644 +--- a/drivers/gpu/drm/meson/meson_encoder_cvbs.c ++++ b/drivers/gpu/drm/meson/meson_encoder_cvbs.c +@@ -294,6 +294,5 @@ void meson_encoder_cvbs_remove(struct meson_drm *priv) + if (priv->encoders[MESON_ENC_CVBS]) { + meson_encoder_cvbs = priv->encoders[MESON_ENC_CVBS]; + drm_bridge_remove(&meson_encoder_cvbs->bridge); +- drm_bridge_remove(meson_encoder_cvbs->next_bridge); + } + } +diff --git a/drivers/gpu/drm/meson/meson_encoder_dsi.c b/drivers/gpu/drm/meson/meson_encoder_dsi.c +index 3f93c70488cad..311b91630fbe5 100644 +--- a/drivers/gpu/drm/meson/meson_encoder_dsi.c ++++ b/drivers/gpu/drm/meson/meson_encoder_dsi.c +@@ -168,6 +168,5 @@ void meson_encoder_dsi_remove(struct meson_drm *priv) + if (priv->encoders[MESON_ENC_DSI]) { + meson_encoder_dsi = priv->encoders[MESON_ENC_DSI]; + drm_bridge_remove(&meson_encoder_dsi->bridge); +- drm_bridge_remove(meson_encoder_dsi->next_bridge); + } + } +diff --git a/drivers/gpu/drm/meson/meson_encoder_hdmi.c b/drivers/gpu/drm/meson/meson_encoder_hdmi.c +index 25ea765586908..c4686568c9ca5 100644 +--- a/drivers/gpu/drm/meson/meson_encoder_hdmi.c ++++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.c +@@ -474,6 +474,5 @@ void meson_encoder_hdmi_remove(struct meson_drm *priv) + if (priv->encoders[MESON_ENC_HDMI]) { + meson_encoder_hdmi = priv->encoders[MESON_ENC_HDMI]; + drm_bridge_remove(&meson_encoder_hdmi->bridge); +- drm_bridge_remove(meson_encoder_hdmi->next_bridge); + } + } +diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/r535.c +index 4135690326f44..3a30bea30e366 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/r535.c ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/r535.c +@@ -168,12 +168,11 @@ r535_bar_new_(const struct nvkm_bar_func *hw, struct nvkm_device *device, + rm->flush = r535_bar_flush; + + ret = gf100_bar_new_(rm, device, type, inst, &bar); +- *pbar = bar; + if (ret) { +- if (!bar) +- kfree(rm); ++ kfree(rm); + return ret; + } ++ *pbar = bar; + + bar->flushBAR2PhysMode = ioremap(device->func->resource_addr(device, 3), PAGE_SIZE); + if (!bar->flushBAR2PhysMode) +diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c +index 19188683c8fca..8c2bf1c16f2a9 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c +@@ -154,11 +154,17 @@ shadow_fw_init(struct nvkm_bios *bios, const char *name) + return (void *)fw; + } + ++static void ++shadow_fw_release(void *fw) ++{ ++ release_firmware(fw); ++} ++ + static const struct nvbios_source + shadow_fw = { + .name = "firmware", + .init = shadow_fw_init, +- .fini = (void(*)(void *))release_firmware, ++ .fini = shadow_fw_release, + .read = shadow_fw_read, + .rw = false, + }; +diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +index 6208ddd929645..a41735ab60683 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +@@ -1950,20 +1950,20 @@ nvkm_gsp_radix3_dtor(struct nvkm_gsp *gsp, struct nvkm_gsp_radix3 *rx3) + * See kgspCreateRadix3_IMPL + */ + static int +-nvkm_gsp_radix3_sg(struct nvkm_device *device, struct sg_table *sgt, u64 size, ++nvkm_gsp_radix3_sg(struct nvkm_gsp *gsp, struct sg_table *sgt, u64 size, + struct nvkm_gsp_radix3 *rx3) + { + u64 addr; + + for (int i = ARRAY_SIZE(rx3->mem) - 1; i >= 0; i--) { + u64 *ptes; +- int idx; ++ size_t bufsize; ++ int ret, idx; + +- rx3->mem[i].size = ALIGN((size / GSP_PAGE_SIZE) * sizeof(u64), GSP_PAGE_SIZE); +- rx3->mem[i].data = dma_alloc_coherent(device->dev, rx3->mem[i].size, +- &rx3->mem[i].addr, GFP_KERNEL); +- if (WARN_ON(!rx3->mem[i].data)) +- return -ENOMEM; ++ bufsize = ALIGN((size / GSP_PAGE_SIZE) * sizeof(u64), GSP_PAGE_SIZE); ++ ret = nvkm_gsp_mem_ctor(gsp, bufsize, &rx3->mem[i]); ++ if (ret) ++ return ret; + + ptes = rx3->mem[i].data; + if (i == 2) { +@@ -2003,7 +2003,7 @@ r535_gsp_fini(struct nvkm_gsp *gsp, bool suspend) + if (ret) + return ret; + +- ret = nvkm_gsp_radix3_sg(gsp->subdev.device, &gsp->sr.sgt, len, &gsp->sr.radix3); ++ ret = nvkm_gsp_radix3_sg(gsp, &gsp->sr.sgt, len, &gsp->sr.radix3); + if (ret) + return ret; + +@@ -2211,7 +2211,7 @@ r535_gsp_oneinit(struct nvkm_gsp *gsp) + memcpy(gsp->sig.data, data, size); + + /* Build radix3 page table for ELF image. */ +- ret = nvkm_gsp_radix3_sg(device, &gsp->fw.mem.sgt, gsp->fw.len, &gsp->radix3); ++ ret = nvkm_gsp_radix3_sg(gsp, &gsp->fw.mem.sgt, gsp->fw.len, &gsp->radix3); + if (ret) + return ret; + +diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c +index fe610a3cace00..dbc96984d331f 100644 +--- a/drivers/gpu/drm/ttm/ttm_pool.c ++++ b/drivers/gpu/drm/ttm/ttm_pool.c +@@ -387,7 +387,7 @@ static void ttm_pool_free_range(struct ttm_pool *pool, struct ttm_tt *tt, + enum ttm_caching caching, + pgoff_t start_page, pgoff_t end_page) + { +- struct page **pages = tt->pages; ++ struct page **pages = &tt->pages[start_page]; + unsigned int order; + pgoff_t i, nr; + +diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c +index fd6d8f1d9b8f6..6ef0c88e3e60a 100644 +--- a/drivers/hid/hid-logitech-hidpp.c ++++ b/drivers/hid/hid-logitech-hidpp.c +@@ -4610,6 +4610,8 @@ static const struct hid_device_id hidpp_devices[] = { + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC088) }, + { /* Logitech G Pro X Superlight Gaming Mouse over USB */ + 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) }, + + { /* G935 Gaming Headset */ + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0x0a87), +diff --git a/drivers/hid/hid-nvidia-shield.c b/drivers/hid/hid-nvidia-shield.c +index 82d0a77359c46..58b15750dbb0a 100644 +--- a/drivers/hid/hid-nvidia-shield.c ++++ b/drivers/hid/hid-nvidia-shield.c +@@ -800,6 +800,8 @@ static inline int thunderstrike_led_create(struct thunderstrike *ts) + + led->name = devm_kasprintf(&ts->base.hdev->dev, GFP_KERNEL, + "thunderstrike%d:blue:led", ts->id); ++ if (!led->name) ++ return -ENOMEM; + led->max_brightness = 1; + led->flags = LED_CORE_SUSPENDRESUME | LED_RETAIN_AT_SHUTDOWN; + led->brightness_get = &thunderstrike_led_get_brightness; +@@ -831,6 +833,8 @@ static inline int thunderstrike_psy_create(struct shield_device *shield_dev) + shield_dev->battery_dev.desc.name = + devm_kasprintf(&ts->base.hdev->dev, GFP_KERNEL, + "thunderstrike_%d", ts->id); ++ if (!shield_dev->battery_dev.desc.name) ++ return -ENOMEM; + + shield_dev->battery_dev.psy = power_supply_register( + &hdev->dev, &shield_dev->battery_dev.desc, &psy_cfg); +diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c +index 95f4c0b00b2d8..b8fc8d1ef20df 100644 +--- a/drivers/hwmon/coretemp.c ++++ b/drivers/hwmon/coretemp.c +@@ -41,7 +41,7 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius"); + + #define PKG_SYSFS_ATTR_NO 1 /* Sysfs attribute for package temp */ + #define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */ +-#define NUM_REAL_CORES 128 /* Number of Real cores per cpu */ ++#define NUM_REAL_CORES 512 /* Number of Real cores per cpu */ + #define CORETEMP_NAME_LENGTH 28 /* String Length of attrs */ + #define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */ + #define TOTAL_ATTRS (MAX_CORE_ATTRS + 1) +diff --git a/drivers/hwmon/nct6775-core.c b/drivers/hwmon/nct6775-core.c +index 92a49fafe2c02..f3bf2e4701c38 100644 +--- a/drivers/hwmon/nct6775-core.c ++++ b/drivers/hwmon/nct6775-core.c +@@ -3512,6 +3512,7 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, + const u16 *reg_temp_mon, *reg_temp_alternate, *reg_temp_crit; + const u16 *reg_temp_crit_l = NULL, *reg_temp_crit_h = NULL; + int num_reg_temp, num_reg_temp_mon, num_reg_tsi_temp; ++ int num_reg_temp_config; + struct device *hwmon_dev; + struct sensor_template_group tsi_temp_tg; + +@@ -3594,6 +3595,7 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, + reg_temp_over = NCT6106_REG_TEMP_OVER; + reg_temp_hyst = NCT6106_REG_TEMP_HYST; + reg_temp_config = NCT6106_REG_TEMP_CONFIG; ++ num_reg_temp_config = ARRAY_SIZE(NCT6106_REG_TEMP_CONFIG); + reg_temp_alternate = NCT6106_REG_TEMP_ALTERNATE; + reg_temp_crit = NCT6106_REG_TEMP_CRIT; + reg_temp_crit_l = NCT6106_REG_TEMP_CRIT_L; +@@ -3669,6 +3671,7 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, + reg_temp_over = NCT6106_REG_TEMP_OVER; + reg_temp_hyst = NCT6106_REG_TEMP_HYST; + reg_temp_config = NCT6106_REG_TEMP_CONFIG; ++ num_reg_temp_config = ARRAY_SIZE(NCT6106_REG_TEMP_CONFIG); + reg_temp_alternate = NCT6106_REG_TEMP_ALTERNATE; + reg_temp_crit = NCT6106_REG_TEMP_CRIT; + reg_temp_crit_l = NCT6106_REG_TEMP_CRIT_L; +@@ -3746,6 +3749,7 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, + reg_temp_over = NCT6775_REG_TEMP_OVER; + reg_temp_hyst = NCT6775_REG_TEMP_HYST; + reg_temp_config = NCT6775_REG_TEMP_CONFIG; ++ num_reg_temp_config = ARRAY_SIZE(NCT6775_REG_TEMP_CONFIG); + reg_temp_alternate = NCT6775_REG_TEMP_ALTERNATE; + reg_temp_crit = NCT6775_REG_TEMP_CRIT; + +@@ -3821,6 +3825,7 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, + reg_temp_over = NCT6775_REG_TEMP_OVER; + reg_temp_hyst = NCT6775_REG_TEMP_HYST; + reg_temp_config = NCT6776_REG_TEMP_CONFIG; ++ num_reg_temp_config = ARRAY_SIZE(NCT6776_REG_TEMP_CONFIG); + reg_temp_alternate = NCT6776_REG_TEMP_ALTERNATE; + reg_temp_crit = NCT6776_REG_TEMP_CRIT; + +@@ -3900,6 +3905,7 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, + reg_temp_over = NCT6779_REG_TEMP_OVER; + reg_temp_hyst = NCT6779_REG_TEMP_HYST; + reg_temp_config = NCT6779_REG_TEMP_CONFIG; ++ num_reg_temp_config = ARRAY_SIZE(NCT6779_REG_TEMP_CONFIG); + reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE; + reg_temp_crit = NCT6779_REG_TEMP_CRIT; + +@@ -4034,6 +4040,7 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, + reg_temp_over = NCT6779_REG_TEMP_OVER; + reg_temp_hyst = NCT6779_REG_TEMP_HYST; + reg_temp_config = NCT6779_REG_TEMP_CONFIG; ++ num_reg_temp_config = ARRAY_SIZE(NCT6779_REG_TEMP_CONFIG); + reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE; + reg_temp_crit = NCT6779_REG_TEMP_CRIT; + +@@ -4123,6 +4130,7 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, + reg_temp_over = NCT6798_REG_TEMP_OVER; + reg_temp_hyst = NCT6798_REG_TEMP_HYST; + reg_temp_config = NCT6779_REG_TEMP_CONFIG; ++ num_reg_temp_config = ARRAY_SIZE(NCT6779_REG_TEMP_CONFIG); + reg_temp_alternate = NCT6798_REG_TEMP_ALTERNATE; + reg_temp_crit = NCT6798_REG_TEMP_CRIT; + +@@ -4204,7 +4212,8 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, + = reg_temp_crit[src - 1]; + if (reg_temp_crit_l && reg_temp_crit_l[i]) + data->reg_temp[4][src - 1] = reg_temp_crit_l[i]; +- data->reg_temp_config[src - 1] = reg_temp_config[i]; ++ if (i < num_reg_temp_config) ++ data->reg_temp_config[src - 1] = reg_temp_config[i]; + data->temp_src[src - 1] = src; + continue; + } +@@ -4217,7 +4226,8 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, + data->reg_temp[0][s] = reg_temp[i]; + data->reg_temp[1][s] = reg_temp_over[i]; + data->reg_temp[2][s] = reg_temp_hyst[i]; +- data->reg_temp_config[s] = reg_temp_config[i]; ++ if (i < num_reg_temp_config) ++ data->reg_temp_config[s] = reg_temp_config[i]; + if (reg_temp_crit_h && reg_temp_crit_h[i]) + data->reg_temp[3][s] = reg_temp_crit_h[i]; + else if (reg_temp_crit[src - 1]) +diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c +index 1775a79aeba2a..0951bfdc89cfa 100644 +--- a/drivers/i2c/busses/i2c-imx.c ++++ b/drivers/i2c/busses/i2c-imx.c +@@ -803,6 +803,11 @@ static irqreturn_t i2c_imx_slave_handle(struct imx_i2c_struct *i2c_imx, + ctl &= ~I2CR_MTX; + imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR); + imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); ++ ++ /* flag the last byte as processed */ ++ i2c_imx_slave_event(i2c_imx, ++ I2C_SLAVE_READ_PROCESSED, &value); ++ + i2c_imx_slave_finish_op(i2c_imx); + return IRQ_HANDLED; + } +diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c +index faa88d12ee868..cc466dfd792b0 100644 +--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c ++++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c +@@ -1809,7 +1809,7 @@ int bnxt_re_modify_srq(struct ib_srq *ib_srq, struct ib_srq_attr *srq_attr, + switch (srq_attr_mask) { + case IB_SRQ_MAX_WR: + /* SRQ resize is not supported */ +- break; ++ return -EINVAL; + case IB_SRQ_LIMIT: + /* Change the SRQ threshold */ + if (srq_attr->srq_limit > srq->qplib_srq.max_wqe) +@@ -1824,13 +1824,12 @@ int bnxt_re_modify_srq(struct ib_srq *ib_srq, struct ib_srq_attr *srq_attr, + /* On success, update the shadow */ + srq->srq_limit = srq_attr->srq_limit; + /* No need to Build and send response back to udata */ +- break; ++ return 0; + default: + ibdev_err(&rdev->ibdev, + "Unsupported srq_attr_mask 0x%x", srq_attr_mask); + return -EINVAL; + } +- return 0; + } + + int bnxt_re_query_srq(struct ib_srq *ib_srq, struct ib_srq_attr *srq_attr) +diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c +index abbabea7f5fa3..2a62239187622 100644 +--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c ++++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c +@@ -748,7 +748,8 @@ int bnxt_qplib_query_srq(struct bnxt_qplib_res *res, + bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, &sbuf, sizeof(req), + sizeof(resp), 0); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); +- srq->threshold = le16_to_cpu(sb->srq_limit); ++ if (!rc) ++ srq->threshold = le16_to_cpu(sb->srq_limit); + dma_free_coherent(&rcfw->pdev->dev, sbuf.size, + sbuf.sb, sbuf.dma_addr); + +diff --git a/drivers/infiniband/hw/hfi1/pio.c b/drivers/infiniband/hw/hfi1/pio.c +index 68c621ff59d03..5a91cbda4aee6 100644 +--- a/drivers/infiniband/hw/hfi1/pio.c ++++ b/drivers/infiniband/hw/hfi1/pio.c +@@ -2086,7 +2086,7 @@ int init_credit_return(struct hfi1_devdata *dd) + "Unable to allocate credit return DMA range for NUMA %d\n", + i); + ret = -ENOMEM; +- goto done; ++ goto free_cr_base; + } + } + set_dev_node(&dd->pcidev->dev, dd->node); +@@ -2094,6 +2094,10 @@ int init_credit_return(struct hfi1_devdata *dd) + ret = 0; + done: + return ret; ++ ++free_cr_base: ++ free_credit_return(dd); ++ goto done; + } + + void free_credit_return(struct hfi1_devdata *dd) +diff --git a/drivers/infiniband/hw/hfi1/sdma.c b/drivers/infiniband/hw/hfi1/sdma.c +index 6e5ac2023328a..b67d23b1f2862 100644 +--- a/drivers/infiniband/hw/hfi1/sdma.c ++++ b/drivers/infiniband/hw/hfi1/sdma.c +@@ -3158,7 +3158,7 @@ int _pad_sdma_tx_descs(struct hfi1_devdata *dd, struct sdma_txreq *tx) + { + int rval = 0; + +- if ((unlikely(tx->num_desc + 1 == tx->desc_limit))) { ++ if ((unlikely(tx->num_desc == tx->desc_limit))) { + rval = _extend_sdma_tx_descs(dd, tx); + if (rval) { + __sdma_txclean(dd, tx); +diff --git a/drivers/infiniband/hw/irdma/defs.h b/drivers/infiniband/hw/irdma/defs.h +index 8fb752f2eda29..2cb4b96db7212 100644 +--- a/drivers/infiniband/hw/irdma/defs.h ++++ b/drivers/infiniband/hw/irdma/defs.h +@@ -346,6 +346,7 @@ enum irdma_cqp_op_type { + #define IRDMA_AE_LLP_TOO_MANY_KEEPALIVE_RETRIES 0x050b + #define IRDMA_AE_LLP_DOUBT_REACHABILITY 0x050c + #define IRDMA_AE_LLP_CONNECTION_ESTABLISHED 0x050e ++#define IRDMA_AE_LLP_TOO_MANY_RNRS 0x050f + #define IRDMA_AE_RESOURCE_EXHAUSTION 0x0520 + #define IRDMA_AE_RESET_SENT 0x0601 + #define IRDMA_AE_TERMINATE_SENT 0x0602 +diff --git a/drivers/infiniband/hw/irdma/hw.c b/drivers/infiniband/hw/irdma/hw.c +index bd4b2b8964444..ad50b77282f8a 100644 +--- a/drivers/infiniband/hw/irdma/hw.c ++++ b/drivers/infiniband/hw/irdma/hw.c +@@ -387,6 +387,7 @@ static void irdma_process_aeq(struct irdma_pci_f *rf) + case IRDMA_AE_LLP_TOO_MANY_RETRIES: + case IRDMA_AE_LCE_QP_CATASTROPHIC: + case IRDMA_AE_LCE_FUNCTION_CATASTROPHIC: ++ case IRDMA_AE_LLP_TOO_MANY_RNRS: + case IRDMA_AE_LCE_CQ_CATASTROPHIC: + case IRDMA_AE_UDA_XMIT_DGRAM_TOO_LONG: + default: +@@ -570,6 +571,13 @@ static void irdma_destroy_irq(struct irdma_pci_f *rf, + dev->irq_ops->irdma_dis_irq(dev, msix_vec->idx); + irq_update_affinity_hint(msix_vec->irq, NULL); + free_irq(msix_vec->irq, dev_id); ++ if (rf == dev_id) { ++ tasklet_kill(&rf->dpc_tasklet); ++ } else { ++ struct irdma_ceq *iwceq = (struct irdma_ceq *)dev_id; ++ ++ tasklet_kill(&iwceq->dpc_tasklet); ++ } + } + + /** +diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c +index b5eb8d421988c..0b046c061742b 100644 +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -839,7 +839,9 @@ static int irdma_validate_qp_attrs(struct ib_qp_init_attr *init_attr, + + if (init_attr->cap.max_inline_data > uk_attrs->max_hw_inline || + init_attr->cap.max_send_sge > uk_attrs->max_hw_wq_frags || +- init_attr->cap.max_recv_sge > uk_attrs->max_hw_wq_frags) ++ init_attr->cap.max_recv_sge > uk_attrs->max_hw_wq_frags || ++ init_attr->cap.max_send_wr > uk_attrs->max_hw_wq_quanta || ++ init_attr->cap.max_recv_wr > uk_attrs->max_hw_rq_quanta) + return -EINVAL; + + if (rdma_protocol_roce(&iwdev->ibdev, 1)) { +@@ -2184,9 +2186,8 @@ static int irdma_create_cq(struct ib_cq *ibcq, + info.cq_base_pa = iwcq->kmem.pa; + } + +- if (dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) +- info.shadow_read_threshold = min(info.cq_uk_init_info.cq_size / 2, +- (u32)IRDMA_MAX_CQ_READ_THRESH); ++ info.shadow_read_threshold = min(info.cq_uk_init_info.cq_size / 2, ++ (u32)IRDMA_MAX_CQ_READ_THRESH); + + if (irdma_sc_cq_init(cq, &info)) { + ibdev_dbg(&iwdev->ibdev, "VERBS: init cq fail\n"); +diff --git a/drivers/infiniband/hw/mlx5/cong.c b/drivers/infiniband/hw/mlx5/cong.c +index f87531318feb8..a78a067e3ce7f 100644 +--- a/drivers/infiniband/hw/mlx5/cong.c ++++ b/drivers/infiniband/hw/mlx5/cong.c +@@ -458,6 +458,12 @@ void mlx5_ib_init_cong_debugfs(struct mlx5_ib_dev *dev, u32 port_num) + dbg_cc_params->root = debugfs_create_dir("cc_params", mlx5_debugfs_get_dev_root(mdev)); + + for (i = 0; i < MLX5_IB_DBG_CC_MAX; i++) { ++ if ((i == MLX5_IB_DBG_CC_GENERAL_RTT_RESP_DSCP_VALID || ++ i == MLX5_IB_DBG_CC_GENERAL_RTT_RESP_DSCP)) ++ if (!MLX5_CAP_GEN(mdev, roce) || ++ !MLX5_CAP_ROCE(mdev, roce_cc_general)) ++ continue; ++ + dbg_cc_params->params[i].offset = i; + dbg_cc_params->params[i].dev = dev; + dbg_cc_params->params[i].port_num = port_num; +diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c +index 7887a6786ed43..f118ce0a9a617 100644 +--- a/drivers/infiniband/hw/qedr/verbs.c ++++ b/drivers/infiniband/hw/qedr/verbs.c +@@ -1879,8 +1879,17 @@ static int qedr_create_user_qp(struct qedr_dev *dev, + /* RQ - read access only (0) */ + rc = qedr_init_user_queue(udata, dev, &qp->urq, ureq.rq_addr, + ureq.rq_len, true, 0, alloc_and_init); +- if (rc) ++ if (rc) { ++ ib_umem_release(qp->usq.umem); ++ qp->usq.umem = NULL; ++ if (rdma_protocol_roce(&dev->ibdev, 1)) { ++ qedr_free_pbl(dev, &qp->usq.pbl_info, ++ qp->usq.pbl_tbl); ++ } else { ++ kfree(qp->usq.pbl_tbl); ++ } + return rc; ++ } + } + + memset(&in_params, 0, sizeof(in_params)); +diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c +index 58f70cfec45a7..040234c01be4d 100644 +--- a/drivers/infiniband/ulp/srpt/ib_srpt.c ++++ b/drivers/infiniband/ulp/srpt/ib_srpt.c +@@ -79,12 +79,16 @@ module_param(srpt_srq_size, int, 0444); + MODULE_PARM_DESC(srpt_srq_size, + "Shared receive queue (SRQ) size."); + ++static int srpt_set_u64_x(const char *buffer, const struct kernel_param *kp) ++{ ++ return kstrtou64(buffer, 16, (u64 *)kp->arg); ++} + static int srpt_get_u64_x(char *buffer, const struct kernel_param *kp) + { + return sprintf(buffer, "0x%016llx\n", *(u64 *)kp->arg); + } +-module_param_call(srpt_service_guid, NULL, srpt_get_u64_x, &srpt_service_guid, +- 0444); ++module_param_call(srpt_service_guid, srpt_set_u64_x, srpt_get_u64_x, ++ &srpt_service_guid, 0444); + MODULE_PARM_DESC(srpt_service_guid, + "Using this value for ioc_guid, id_ext, and cm_listen_id instead of using the node_guid of the first HCA."); + +@@ -210,10 +214,12 @@ static const char *get_ch_state_name(enum rdma_ch_state s) + /** + * srpt_qp_event - QP event callback function + * @event: Description of the event that occurred. +- * @ch: SRPT RDMA channel. ++ * @ptr: SRPT RDMA channel. + */ +-static void srpt_qp_event(struct ib_event *event, struct srpt_rdma_ch *ch) ++static void srpt_qp_event(struct ib_event *event, void *ptr) + { ++ struct srpt_rdma_ch *ch = ptr; ++ + pr_debug("QP event %d on ch=%p sess_name=%s-%d state=%s\n", + event->event, ch, ch->sess_name, ch->qp->qp_num, + get_ch_state_name(ch->state)); +@@ -1807,8 +1813,7 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch) + ch->cq_size = ch->rq_size + sq_size; + + qp_init->qp_context = (void *)ch; +- qp_init->event_handler +- = (void(*)(struct ib_event *, void*))srpt_qp_event; ++ qp_init->event_handler = srpt_qp_event; + qp_init->send_cq = ch->cq; + qp_init->recv_cq = ch->cq; + qp_init->sq_sig_type = IB_SIGNAL_REQ_WR; +diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c +index e2c1848182de9..d0bb3edfd0a09 100644 +--- a/drivers/input/joystick/xpad.c ++++ b/drivers/input/joystick/xpad.c +@@ -294,6 +294,7 @@ static const struct xpad_device { + { 0x1689, 0xfd00, "Razer Onza Tournament Edition", 0, XTYPE_XBOX360 }, + { 0x1689, 0xfd01, "Razer Onza Classic Edition", 0, XTYPE_XBOX360 }, + { 0x1689, 0xfe00, "Razer Sabertooth", 0, XTYPE_XBOX360 }, ++ { 0x17ef, 0x6182, "Lenovo Legion Controller for Windows", 0, XTYPE_XBOX360 }, + { 0x1949, 0x041a, "Amazon Game Controller", 0, XTYPE_XBOX360 }, + { 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 }, + { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, +@@ -491,6 +492,7 @@ static const struct usb_device_id xpad_table[] = { + XPAD_XBOX360_VENDOR(0x15e4), /* Numark Xbox 360 controllers */ + XPAD_XBOX360_VENDOR(0x162e), /* Joytech Xbox 360 controllers */ + XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */ ++ XPAD_XBOX360_VENDOR(0x17ef), /* Lenovo */ + XPAD_XBOX360_VENDOR(0x1949), /* Amazon controllers */ + XPAD_XBOX360_VENDOR(0x1bad), /* Harmonix Rock Band guitar and drums */ + XPAD_XBOX360_VENDOR(0x20d6), /* PowerA controllers */ +diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h +index cd45a65e17f2c..dfc6c581873b7 100644 +--- a/drivers/input/serio/i8042-acpipnpio.h ++++ b/drivers/input/serio/i8042-acpipnpio.h +@@ -634,6 +634,14 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { + }, + .driver_data = (void *)(SERIO_QUIRK_NOAUX) + }, ++ { ++ /* Fujitsu Lifebook U728 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U728"), ++ }, ++ .driver_data = (void *)(SERIO_QUIRK_NOAUX) ++ }, + { + /* Gigabyte M912 */ + .matches = { +diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c +index af32fbe57b630..b068ff8afbc9a 100644 +--- a/drivers/input/touchscreen/goodix.c ++++ b/drivers/input/touchscreen/goodix.c +@@ -884,7 +884,8 @@ static int goodix_add_acpi_gpio_mappings(struct goodix_ts_data *ts) + } + } + +- if (ts->gpio_count == 2 && ts->gpio_int_idx == 0) { ++ /* Some devices with gpio_int_idx 0 list a third unused GPIO */ ++ if ((ts->gpio_count == 2 || ts->gpio_count == 3) && ts->gpio_int_idx == 0) { + ts->irq_pin_access_method = IRQ_PIN_ACCESS_ACPI_GPIO; + gpio_mapping = acpi_goodix_int_first_gpios; + } else if (ts->gpio_count == 2 && ts->gpio_int_idx == 1) { +diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c +index 353248ab18e76..4a27fbdb2d844 100644 +--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c ++++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c +@@ -246,7 +246,8 @@ static void arm_smmu_mm_arch_invalidate_secondary_tlbs(struct mmu_notifier *mn, + smmu_domain); + } + +- arm_smmu_atc_inv_domain(smmu_domain, mm->pasid, start, size); ++ arm_smmu_atc_inv_domain(smmu_domain, mm_get_enqcmd_pasid(mm), start, ++ size); + } + + static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm) +@@ -264,10 +265,11 @@ static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm) + * DMA may still be running. Keep the cd valid to avoid C_BAD_CD events, + * but disable translation. + */ +- arm_smmu_update_ctx_desc_devices(smmu_domain, mm->pasid, &quiet_cd); ++ arm_smmu_update_ctx_desc_devices(smmu_domain, mm_get_enqcmd_pasid(mm), ++ &quiet_cd); + + arm_smmu_tlb_inv_asid(smmu_domain->smmu, smmu_mn->cd->asid); +- arm_smmu_atc_inv_domain(smmu_domain, mm->pasid, 0, 0); ++ arm_smmu_atc_inv_domain(smmu_domain, mm_get_enqcmd_pasid(mm), 0, 0); + + smmu_mn->cleared = true; + mutex_unlock(&sva_lock); +@@ -290,10 +292,8 @@ arm_smmu_mmu_notifier_get(struct arm_smmu_domain *smmu_domain, + struct mm_struct *mm) + { + int ret; +- unsigned long flags; + struct arm_smmu_ctx_desc *cd; + struct arm_smmu_mmu_notifier *smmu_mn; +- struct arm_smmu_master *master; + + list_for_each_entry(smmu_mn, &smmu_domain->mmu_notifiers, list) { + if (smmu_mn->mn.mm == mm) { +@@ -323,25 +323,9 @@ arm_smmu_mmu_notifier_get(struct arm_smmu_domain *smmu_domain, + goto err_free_cd; + } + +- spin_lock_irqsave(&smmu_domain->devices_lock, flags); +- list_for_each_entry(master, &smmu_domain->devices, domain_head) { +- ret = arm_smmu_write_ctx_desc(master, mm->pasid, cd); +- if (ret) { +- list_for_each_entry_from_reverse(master, &smmu_domain->devices, domain_head) +- arm_smmu_write_ctx_desc(master, mm->pasid, NULL); +- break; +- } +- } +- spin_unlock_irqrestore(&smmu_domain->devices_lock, flags); +- if (ret) +- goto err_put_notifier; +- + list_add(&smmu_mn->list, &smmu_domain->mmu_notifiers); + return smmu_mn; + +-err_put_notifier: +- /* Frees smmu_mn */ +- mmu_notifier_put(&smmu_mn->mn); + err_free_cd: + arm_smmu_free_shared_cd(cd); + return ERR_PTR(ret); +@@ -358,15 +342,14 @@ static void arm_smmu_mmu_notifier_put(struct arm_smmu_mmu_notifier *smmu_mn) + + list_del(&smmu_mn->list); + +- arm_smmu_update_ctx_desc_devices(smmu_domain, mm->pasid, NULL); +- + /* + * If we went through clear(), we've already invalidated, and no + * new TLB entry can have been formed. + */ + if (!smmu_mn->cleared) { + arm_smmu_tlb_inv_asid(smmu_domain->smmu, cd->asid); +- arm_smmu_atc_inv_domain(smmu_domain, mm->pasid, 0, 0); ++ arm_smmu_atc_inv_domain(smmu_domain, mm_get_enqcmd_pasid(mm), 0, ++ 0); + } + + /* Frees smmu_mn */ +@@ -374,7 +357,8 @@ static void arm_smmu_mmu_notifier_put(struct arm_smmu_mmu_notifier *smmu_mn) + arm_smmu_free_shared_cd(cd); + } + +-static int __arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm) ++static int __arm_smmu_sva_bind(struct device *dev, ioasid_t pasid, ++ struct mm_struct *mm) + { + int ret; + struct arm_smmu_bond *bond; +@@ -397,9 +381,15 @@ static int __arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm) + goto err_free_bond; + } + ++ ret = arm_smmu_write_ctx_desc(master, pasid, bond->smmu_mn->cd); ++ if (ret) ++ goto err_put_notifier; ++ + list_add(&bond->list, &master->bonds); + return 0; + ++err_put_notifier: ++ arm_smmu_mmu_notifier_put(bond->smmu_mn); + err_free_bond: + kfree(bond); + return ret; +@@ -561,6 +551,9 @@ void arm_smmu_sva_remove_dev_pasid(struct iommu_domain *domain, + struct arm_smmu_master *master = dev_iommu_priv_get(dev); + + mutex_lock(&sva_lock); ++ ++ arm_smmu_write_ctx_desc(master, id, NULL); ++ + list_for_each_entry(t, &master->bonds, list) { + if (t->mm == mm) { + bond = t; +@@ -583,7 +576,7 @@ static int arm_smmu_sva_set_dev_pasid(struct iommu_domain *domain, + struct mm_struct *mm = domain->mm; + + mutex_lock(&sva_lock); +- ret = __arm_smmu_sva_bind(dev, mm); ++ ret = __arm_smmu_sva_bind(dev, id, mm); + mutex_unlock(&sva_lock); + + return ret; +diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c +index 897159dba47de..a8366b1f4f48b 100644 +--- a/drivers/iommu/intel/iommu.c ++++ b/drivers/iommu/intel/iommu.c +@@ -540,8 +540,6 @@ static int domain_update_device_node(struct dmar_domain *domain) + return nid; + } + +-static void domain_update_iotlb(struct dmar_domain *domain); +- + /* Return the super pagesize bitmap if supported. */ + static unsigned long domain_super_pgsize_bitmap(struct dmar_domain *domain) + { +@@ -1362,7 +1360,7 @@ domain_lookup_dev_info(struct dmar_domain *domain, + return NULL; + } + +-static void domain_update_iotlb(struct dmar_domain *domain) ++void domain_update_iotlb(struct dmar_domain *domain) + { + struct dev_pasid_info *dev_pasid; + struct device_domain_info *info; +@@ -4071,6 +4069,7 @@ intel_iommu_domain_alloc_user(struct device *dev, u32 flags, + 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; + + /* Must be NESTING domain */ +@@ -4096,11 +4095,16 @@ intel_iommu_domain_alloc_user(struct device *dev, u32 flags, + if (!domain) + return ERR_PTR(-ENOMEM); + +- if (nested_parent) +- to_dmar_domain(domain)->nested_parent = true; ++ dmar_domain = to_dmar_domain(domain); ++ ++ 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 (to_dmar_domain(domain)->use_first_level) { ++ if (dmar_domain->use_first_level) { + iommu_domain_free(domain); + return ERR_PTR(-EOPNOTSUPP); + } +@@ -4112,8 +4116,12 @@ intel_iommu_domain_alloc_user(struct device *dev, u32 flags, + + static void intel_iommu_domain_free(struct iommu_domain *domain) + { ++ struct dmar_domain *dmar_domain = to_dmar_domain(domain); ++ ++ WARN_ON(dmar_domain->nested_parent && ++ !list_empty(&dmar_domain->s1_domains)); + if (domain != &si_domain->domain) +- domain_exit(to_dmar_domain(domain)); ++ domain_exit(dmar_domain); + } + + int prepare_domain_attach_device(struct iommu_domain *domain, +@@ -4857,21 +4865,70 @@ static void *intel_iommu_hw_info(struct device *dev, u32 *length, u32 *type) + return vtd; + } + ++/* ++ * Set dirty tracking for the device list of a domain. The caller must ++ * hold the domain->lock when calling it. ++ */ ++static int device_set_dirty_tracking(struct list_head *devices, bool enable) ++{ ++ struct device_domain_info *info; ++ int ret = 0; ++ ++ list_for_each_entry(info, devices, link) { ++ ret = intel_pasid_setup_dirty_tracking(info->iommu, info->dev, ++ IOMMU_NO_PASID, enable); ++ if (ret) ++ break; ++ } ++ ++ return ret; ++} ++ ++static int parent_domain_set_dirty_tracking(struct dmar_domain *domain, ++ bool enable) ++{ ++ struct dmar_domain *s1_domain; ++ unsigned long flags; ++ int ret; ++ ++ spin_lock(&domain->s1_lock); ++ list_for_each_entry(s1_domain, &domain->s1_domains, s2_link) { ++ spin_lock_irqsave(&s1_domain->lock, flags); ++ ret = device_set_dirty_tracking(&s1_domain->devices, enable); ++ spin_unlock_irqrestore(&s1_domain->lock, flags); ++ if (ret) ++ goto err_unwind; ++ } ++ spin_unlock(&domain->s1_lock); ++ return 0; ++ ++err_unwind: ++ list_for_each_entry(s1_domain, &domain->s1_domains, s2_link) { ++ spin_lock_irqsave(&s1_domain->lock, flags); ++ device_set_dirty_tracking(&s1_domain->devices, ++ domain->dirty_tracking); ++ spin_unlock_irqrestore(&s1_domain->lock, flags); ++ } ++ spin_unlock(&domain->s1_lock); ++ return ret; ++} ++ + static int intel_iommu_set_dirty_tracking(struct iommu_domain *domain, + bool enable) + { + struct dmar_domain *dmar_domain = to_dmar_domain(domain); +- struct device_domain_info *info; + int ret; + + spin_lock(&dmar_domain->lock); + if (dmar_domain->dirty_tracking == enable) + goto out_unlock; + +- list_for_each_entry(info, &dmar_domain->devices, link) { +- ret = intel_pasid_setup_dirty_tracking(info->iommu, +- info->domain, info->dev, +- IOMMU_NO_PASID, enable); ++ ret = device_set_dirty_tracking(&dmar_domain->devices, enable); ++ if (ret) ++ goto err_unwind; ++ ++ if (dmar_domain->nested_parent) { ++ ret = parent_domain_set_dirty_tracking(dmar_domain, enable); + if (ret) + goto err_unwind; + } +@@ -4883,10 +4940,8 @@ static int intel_iommu_set_dirty_tracking(struct iommu_domain *domain, + return 0; + + err_unwind: +- list_for_each_entry(info, &dmar_domain->devices, link) +- intel_pasid_setup_dirty_tracking(info->iommu, dmar_domain, +- info->dev, IOMMU_NO_PASID, +- dmar_domain->dirty_tracking); ++ device_set_dirty_tracking(&dmar_domain->devices, ++ dmar_domain->dirty_tracking); + spin_unlock(&dmar_domain->lock); + return ret; + } +diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h +index ce030c5b5772a..efc00d2b4527a 100644 +--- a/drivers/iommu/intel/iommu.h ++++ b/drivers/iommu/intel/iommu.h +@@ -630,6 +630,10 @@ struct dmar_domain { + int agaw; + /* maximum mapped address */ + u64 max_addr; ++ /* Protect the s1_domains list */ ++ spinlock_t s1_lock; ++ /* Track s1_domains nested on this domain */ ++ struct list_head s1_domains; + }; + + /* Nested user domain */ +@@ -640,6 +644,8 @@ struct dmar_domain { + unsigned long s1_pgtbl; + /* page table attributes */ + struct iommu_hwpt_vtd_s1 s1_cfg; ++ /* link to parent domain siblings */ ++ struct list_head s2_link; + }; + }; + +@@ -888,6 +894,7 @@ int qi_submit_sync(struct intel_iommu *iommu, struct qi_desc *desc, + */ + #define QI_OPT_WAIT_DRAIN BIT(0) + ++void domain_update_iotlb(struct dmar_domain *domain); + int domain_attach_iommu(struct dmar_domain *domain, struct intel_iommu *iommu); + void domain_detach_iommu(struct dmar_domain *domain, struct intel_iommu *iommu); + void device_block_translation(struct device *dev); +diff --git a/drivers/iommu/intel/nested.c b/drivers/iommu/intel/nested.c +index b5a5563ab32c6..92e82b33ea979 100644 +--- a/drivers/iommu/intel/nested.c ++++ b/drivers/iommu/intel/nested.c +@@ -65,12 +65,20 @@ static int intel_nested_attach_dev(struct iommu_domain *domain, + list_add(&info->link, &dmar_domain->devices); + spin_unlock_irqrestore(&dmar_domain->lock, flags); + ++ domain_update_iotlb(dmar_domain); ++ + return 0; + } + + static void intel_nested_domain_free(struct iommu_domain *domain) + { +- kfree(to_dmar_domain(domain)); ++ struct dmar_domain *dmar_domain = to_dmar_domain(domain); ++ struct dmar_domain *s2_domain = dmar_domain->s2_domain; ++ ++ spin_lock(&s2_domain->s1_lock); ++ list_del(&dmar_domain->s2_link); ++ spin_unlock(&s2_domain->s1_lock); ++ kfree(dmar_domain); + } + + static const struct iommu_domain_ops intel_nested_domain_ops = { +@@ -113,5 +121,9 @@ struct iommu_domain *intel_nested_domain_alloc(struct iommu_domain *parent, + spin_lock_init(&domain->lock); + xa_init(&domain->iommu_array); + ++ spin_lock(&s2_domain->s1_lock); ++ list_add(&domain->s2_link, &s2_domain->s1_domains); ++ spin_unlock(&s2_domain->s1_lock); ++ + return &domain->domain; + } +diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c +index 74e8e4c17e814..6e102cbbde845 100644 +--- a/drivers/iommu/intel/pasid.c ++++ b/drivers/iommu/intel/pasid.c +@@ -695,7 +695,6 @@ int intel_pasid_setup_second_level(struct intel_iommu *iommu, + * Set up dirty tracking on a second only or nested translation type. + */ + int intel_pasid_setup_dirty_tracking(struct intel_iommu *iommu, +- struct dmar_domain *domain, + struct device *dev, u32 pasid, + bool enabled) + { +@@ -712,7 +711,7 @@ int intel_pasid_setup_dirty_tracking(struct intel_iommu *iommu, + return -ENODEV; + } + +- did = domain_id_iommu(domain, iommu); ++ did = pasid_get_domain_id(pte); + pgtt = pasid_pte_get_pgtt(pte); + if (pgtt != PASID_ENTRY_PGTT_SL_ONLY && + pgtt != PASID_ENTRY_PGTT_NESTED) { +@@ -926,6 +925,8 @@ int intel_pasid_setup_nested(struct intel_iommu *iommu, struct device *dev, + pasid_set_domain_id(pte, did); + pasid_set_address_width(pte, s2_domain->agaw); + pasid_set_page_snoop(pte, !!ecap_smpwc(iommu->ecap)); ++ if (s2_domain->dirty_tracking) ++ pasid_set_ssade(pte); + pasid_set_translation_type(pte, PASID_ENTRY_PGTT_NESTED); + pasid_set_present(pte); + spin_unlock(&iommu->lock); +diff --git a/drivers/iommu/intel/pasid.h b/drivers/iommu/intel/pasid.h +index dd37611175cc1..3568adca1fd82 100644 +--- a/drivers/iommu/intel/pasid.h ++++ b/drivers/iommu/intel/pasid.h +@@ -107,7 +107,6 @@ int intel_pasid_setup_second_level(struct intel_iommu *iommu, + struct dmar_domain *domain, + struct device *dev, u32 pasid); + int intel_pasid_setup_dirty_tracking(struct intel_iommu *iommu, +- struct dmar_domain *domain, + struct device *dev, u32 pasid, + bool enabled); + int intel_pasid_setup_pass_through(struct intel_iommu *iommu, +diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c +index b78671a8a9143..4a2f5699747f1 100644 +--- a/drivers/iommu/iommu-sva.c ++++ b/drivers/iommu/iommu-sva.c +@@ -141,7 +141,7 @@ u32 iommu_sva_get_pasid(struct iommu_sva *handle) + { + struct iommu_domain *domain = handle->domain; + +- return domain->mm->pasid; ++ return mm_get_enqcmd_pasid(domain->mm); + } + EXPORT_SYMBOL_GPL(iommu_sva_get_pasid); + +diff --git a/drivers/iommu/iommufd/hw_pagetable.c b/drivers/iommu/iommufd/hw_pagetable.c +index cbb5df0a6c32f..6f680959b23ed 100644 +--- a/drivers/iommu/iommufd/hw_pagetable.c ++++ b/drivers/iommu/iommufd/hw_pagetable.c +@@ -261,7 +261,8 @@ int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd) + + if (cmd->__reserved) + return -EOPNOTSUPP; +- if (cmd->data_type == IOMMU_HWPT_DATA_NONE && cmd->data_len) ++ if ((cmd->data_type == IOMMU_HWPT_DATA_NONE && cmd->data_len) || ++ (cmd->data_type != IOMMU_HWPT_DATA_NONE && !cmd->data_len)) + return -EINVAL; + + idev = iommufd_get_device(ucmd, cmd->dev_id); +diff --git a/drivers/iommu/iommufd/iova_bitmap.c b/drivers/iommu/iommufd/iova_bitmap.c +index 0a92c9eeaf7f5..db8c46bee1559 100644 +--- a/drivers/iommu/iommufd/iova_bitmap.c ++++ b/drivers/iommu/iommufd/iova_bitmap.c +@@ -100,7 +100,7 @@ struct iova_bitmap { + struct iova_bitmap_map mapped; + + /* userspace address of the bitmap */ +- u64 __user *bitmap; ++ u8 __user *bitmap; + + /* u64 index that @mapped points to */ + unsigned long mapped_base_index; +@@ -113,6 +113,9 @@ struct iova_bitmap { + + /* length of the IOVA range for the whole bitmap */ + size_t length; ++ ++ /* length of the IOVA range set ahead the pinned pages */ ++ unsigned long set_ahead_length; + }; + + /* +@@ -162,7 +165,7 @@ static int iova_bitmap_get(struct iova_bitmap *bitmap) + { + struct iova_bitmap_map *mapped = &bitmap->mapped; + unsigned long npages; +- u64 __user *addr; ++ u8 __user *addr; + long ret; + + /* +@@ -175,18 +178,19 @@ static int iova_bitmap_get(struct iova_bitmap *bitmap) + bitmap->mapped_base_index) * + sizeof(*bitmap->bitmap), PAGE_SIZE); + +- /* +- * We always cap at max number of 'struct page' a base page can fit. +- * This is, for example, on x86 means 2M of bitmap data max. +- */ +- npages = min(npages, PAGE_SIZE / sizeof(struct page *)); +- + /* + * Bitmap address to be pinned is calculated via pointer arithmetic + * with bitmap u64 word index. + */ + addr = bitmap->bitmap + bitmap->mapped_base_index; + ++ /* ++ * We always cap at max number of 'struct page' a base page can fit. ++ * This is, for example, on x86 means 2M of bitmap data max. ++ */ ++ npages = min(npages + !!offset_in_page(addr), ++ PAGE_SIZE / sizeof(struct page *)); ++ + ret = pin_user_pages_fast((unsigned long)addr, npages, + FOLL_WRITE, mapped->pages); + if (ret <= 0) +@@ -247,7 +251,7 @@ struct iova_bitmap *iova_bitmap_alloc(unsigned long iova, size_t length, + + mapped = &bitmap->mapped; + mapped->pgshift = __ffs(page_size); +- bitmap->bitmap = data; ++ bitmap->bitmap = (u8 __user *)data; + bitmap->mapped_total_index = + iova_bitmap_offset_to_index(bitmap, length - 1) + 1; + bitmap->iova = iova; +@@ -304,7 +308,7 @@ static unsigned long iova_bitmap_mapped_remaining(struct iova_bitmap *bitmap) + + remaining = bitmap->mapped_total_index - bitmap->mapped_base_index; + remaining = min_t(unsigned long, remaining, +- bytes / sizeof(*bitmap->bitmap)); ++ DIV_ROUND_UP(bytes, sizeof(*bitmap->bitmap))); + + return remaining; + } +@@ -341,6 +345,32 @@ static bool iova_bitmap_done(struct iova_bitmap *bitmap) + return bitmap->mapped_base_index >= bitmap->mapped_total_index; + } + ++static int iova_bitmap_set_ahead(struct iova_bitmap *bitmap, ++ size_t set_ahead_length) ++{ ++ int ret = 0; ++ ++ while (set_ahead_length > 0 && !iova_bitmap_done(bitmap)) { ++ unsigned long length = iova_bitmap_mapped_length(bitmap); ++ unsigned long iova = iova_bitmap_mapped_iova(bitmap); ++ ++ ret = iova_bitmap_get(bitmap); ++ if (ret) ++ break; ++ ++ length = min(length, set_ahead_length); ++ iova_bitmap_set(bitmap, iova, length); ++ ++ set_ahead_length -= length; ++ bitmap->mapped_base_index += ++ iova_bitmap_offset_to_index(bitmap, length - 1) + 1; ++ iova_bitmap_put(bitmap); ++ } ++ ++ bitmap->set_ahead_length = 0; ++ return ret; ++} ++ + /* + * Advances to the next range, releases the current pinned + * pages and pins the next set of bitmap pages. +@@ -357,6 +387,15 @@ static int iova_bitmap_advance(struct iova_bitmap *bitmap) + if (iova_bitmap_done(bitmap)) + return 0; + ++ /* Iterate, set and skip any bits requested for next iteration */ ++ if (bitmap->set_ahead_length) { ++ int ret; ++ ++ ret = iova_bitmap_set_ahead(bitmap, bitmap->set_ahead_length); ++ if (ret) ++ return ret; ++ } ++ + /* When advancing the index we pin the next set of bitmap pages */ + return iova_bitmap_get(bitmap); + } +@@ -409,6 +448,7 @@ void iova_bitmap_set(struct iova_bitmap *bitmap, + mapped->pgshift) + mapped->pgoff * BITS_PER_BYTE; + unsigned long last_bit = (((iova + length - 1) - mapped->iova) >> + mapped->pgshift) + mapped->pgoff * BITS_PER_BYTE; ++ unsigned long last_page_idx = mapped->npages - 1; + + do { + unsigned int page_idx = cur_bit / BITS_PER_PAGE; +@@ -417,10 +457,18 @@ void iova_bitmap_set(struct iova_bitmap *bitmap, + last_bit - cur_bit + 1); + void *kaddr; + ++ if (unlikely(page_idx > last_page_idx)) ++ break; ++ + kaddr = kmap_local_page(mapped->pages[page_idx]); + bitmap_set(kaddr, offset, nbits); + kunmap_local(kaddr); + cur_bit += nbits; + } while (cur_bit <= last_bit); ++ ++ if (unlikely(cur_bit <= last_bit)) { ++ bitmap->set_ahead_length = ++ ((last_bit - cur_bit + 1) << bitmap->mapped.pgshift); ++ } + } + EXPORT_SYMBOL_NS_GPL(iova_bitmap_set, IOMMUFD); +diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c +index 3632c92cd183c..676c9250d3f28 100644 +--- a/drivers/irqchip/irq-gic-v3-its.c ++++ b/drivers/irqchip/irq-gic-v3-its.c +@@ -3181,6 +3181,7 @@ static void its_cpu_init_lpis(void) + val |= GICR_CTLR_ENABLE_LPIS; + writel_relaxed(val, rbase + GICR_CTLR); + ++out: + if (gic_rdists->has_vlpis && !gic_rdists->has_rvpeid) { + void __iomem *vlpi_base = gic_data_rdist_vlpi_base(); + +@@ -3216,7 +3217,6 @@ static void its_cpu_init_lpis(void) + + /* Make sure the GIC has seen the above */ + dsb(sy); +-out: + gic_data_rdist()->flags |= RD_LOCAL_LPI_ENABLED; + pr_info("GICv3: CPU%d: using %s LPI pending table @%pa\n", + smp_processor_id(), +diff --git a/drivers/irqchip/irq-mbigen.c b/drivers/irqchip/irq-mbigen.c +index 5101a3fb11df5..58881d3139792 100644 +--- a/drivers/irqchip/irq-mbigen.c ++++ b/drivers/irqchip/irq-mbigen.c +@@ -235,22 +235,17 @@ static const struct irq_domain_ops mbigen_domain_ops = { + static int mbigen_of_create_domain(struct platform_device *pdev, + struct mbigen_device *mgn_chip) + { +- struct device *parent; + struct platform_device *child; + struct irq_domain *domain; + struct device_node *np; + u32 num_pins; + int ret = 0; + +- parent = bus_get_dev_root(&platform_bus_type); +- if (!parent) +- return -ENODEV; +- + for_each_child_of_node(pdev->dev.of_node, np) { + if (!of_property_read_bool(np, "interrupt-controller")) + continue; + +- child = of_platform_device_create(np, NULL, parent); ++ child = of_platform_device_create(np, NULL, NULL); + if (!child) { + ret = -ENOMEM; + break; +@@ -273,7 +268,6 @@ static int mbigen_of_create_domain(struct platform_device *pdev, + } + } + +- put_device(parent); + if (ret) + of_node_put(np); + +diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c +index 5b7bc4fd9517c..bf0b40b0fad4b 100644 +--- a/drivers/irqchip/irq-sifive-plic.c ++++ b/drivers/irqchip/irq-sifive-plic.c +@@ -148,7 +148,13 @@ static void plic_irq_eoi(struct irq_data *d) + { + struct plic_handler *handler = this_cpu_ptr(&plic_handlers); + +- writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM); ++ if (unlikely(irqd_irq_disabled(d))) { ++ plic_toggle(handler, d->hwirq, 1); ++ writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM); ++ plic_toggle(handler, d->hwirq, 0); ++ } else { ++ writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM); ++ } + } + + #ifdef CONFIG_SMP +diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c +index 08681f4265205..4ab4e8dcfd3e2 100644 +--- a/drivers/md/dm-crypt.c ++++ b/drivers/md/dm-crypt.c +@@ -62,6 +62,8 @@ struct convert_context { + struct skcipher_request *req; + struct aead_request *req_aead; + } r; ++ bool aead_recheck; ++ bool aead_failed; + + }; + +@@ -82,6 +84,8 @@ struct dm_crypt_io { + blk_status_t error; + sector_t sector; + ++ struct bvec_iter saved_bi_iter; ++ + struct rb_node rb_node; + } CRYPTO_MINALIGN_ATTR; + +@@ -1370,10 +1374,13 @@ static int crypt_convert_block_aead(struct crypt_config *cc, + if (r == -EBADMSG) { + sector_t s = le64_to_cpu(*sector); + +- DMERR_LIMIT("%pg: INTEGRITY AEAD ERROR, sector %llu", +- ctx->bio_in->bi_bdev, s); +- dm_audit_log_bio(DM_MSG_PREFIX, "integrity-aead", +- ctx->bio_in, s, 0); ++ ctx->aead_failed = true; ++ if (ctx->aead_recheck) { ++ DMERR_LIMIT("%pg: INTEGRITY AEAD ERROR, sector %llu", ++ ctx->bio_in->bi_bdev, s); ++ dm_audit_log_bio(DM_MSG_PREFIX, "integrity-aead", ++ ctx->bio_in, s, 0); ++ } + } + + if (!r && cc->iv_gen_ops && cc->iv_gen_ops->post) +@@ -1757,6 +1764,8 @@ static void crypt_io_init(struct dm_crypt_io *io, struct crypt_config *cc, + io->base_bio = bio; + io->sector = sector; + io->error = 0; ++ io->ctx.aead_recheck = false; ++ io->ctx.aead_failed = false; + io->ctx.r.req = NULL; + io->integrity_metadata = NULL; + io->integrity_metadata_from_pool = false; +@@ -1768,6 +1777,8 @@ static void crypt_inc_pending(struct dm_crypt_io *io) + atomic_inc(&io->io_pending); + } + ++static void kcryptd_queue_read(struct dm_crypt_io *io); ++ + /* + * One of the bios was finished. Check for completion of + * the whole request and correctly clean up the buffer. +@@ -1781,6 +1792,15 @@ static void crypt_dec_pending(struct dm_crypt_io *io) + if (!atomic_dec_and_test(&io->io_pending)) + return; + ++ if (likely(!io->ctx.aead_recheck) && unlikely(io->ctx.aead_failed) && ++ cc->on_disk_tag_size && bio_data_dir(base_bio) == READ) { ++ io->ctx.aead_recheck = true; ++ io->ctx.aead_failed = false; ++ io->error = 0; ++ kcryptd_queue_read(io); ++ return; ++ } ++ + if (io->ctx.r.req) + crypt_free_req(cc, io->ctx.r.req, base_bio); + +@@ -1816,15 +1836,19 @@ static void crypt_endio(struct bio *clone) + struct dm_crypt_io *io = clone->bi_private; + struct crypt_config *cc = io->cc; + unsigned int rw = bio_data_dir(clone); +- blk_status_t error; ++ blk_status_t error = clone->bi_status; ++ ++ if (io->ctx.aead_recheck && !error) { ++ kcryptd_queue_crypt(io); ++ return; ++ } + + /* + * free the processed pages + */ +- if (rw == WRITE) ++ if (rw == WRITE || io->ctx.aead_recheck) + crypt_free_buffer_pages(cc, clone); + +- error = clone->bi_status; + bio_put(clone); + + if (rw == READ && !error) { +@@ -1845,6 +1869,22 @@ static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp) + struct crypt_config *cc = io->cc; + struct bio *clone; + ++ if (io->ctx.aead_recheck) { ++ if (!(gfp & __GFP_DIRECT_RECLAIM)) ++ return 1; ++ crypt_inc_pending(io); ++ clone = crypt_alloc_buffer(io, io->base_bio->bi_iter.bi_size); ++ if (unlikely(!clone)) { ++ crypt_dec_pending(io); ++ return 1; ++ } ++ clone->bi_iter.bi_sector = cc->start + io->sector; ++ crypt_convert_init(cc, &io->ctx, clone, clone, io->sector); ++ io->saved_bi_iter = clone->bi_iter; ++ dm_submit_bio_remap(io->base_bio, clone); ++ return 0; ++ } ++ + /* + * We need the original biovec array in order to decrypt the whole bio + * data *afterwards* -- thanks to immutable biovecs we don't need to +@@ -2071,6 +2111,12 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) + io->ctx.bio_out = clone; + io->ctx.iter_out = clone->bi_iter; + ++ if (crypt_integrity_aead(cc)) { ++ bio_copy_data(clone, io->base_bio); ++ io->ctx.bio_in = clone; ++ io->ctx.iter_in = clone->bi_iter; ++ } ++ + sector += bio_sectors(clone); + + crypt_inc_pending(io); +@@ -2107,6 +2153,14 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) + + static void kcryptd_crypt_read_done(struct dm_crypt_io *io) + { ++ if (io->ctx.aead_recheck) { ++ if (!io->error) { ++ io->ctx.bio_in->bi_iter = io->saved_bi_iter; ++ bio_copy_data(io->base_bio, io->ctx.bio_in); ++ } ++ crypt_free_buffer_pages(io->cc, io->ctx.bio_in); ++ bio_put(io->ctx.bio_in); ++ } + crypt_dec_pending(io); + } + +@@ -2136,11 +2190,17 @@ static void kcryptd_crypt_read_convert(struct dm_crypt_io *io) + + crypt_inc_pending(io); + +- crypt_convert_init(cc, &io->ctx, io->base_bio, io->base_bio, +- io->sector); ++ if (io->ctx.aead_recheck) { ++ io->ctx.cc_sector = io->sector + cc->iv_offset; ++ r = crypt_convert(cc, &io->ctx, ++ test_bit(DM_CRYPT_NO_READ_WORKQUEUE, &cc->flags), true); ++ } else { ++ crypt_convert_init(cc, &io->ctx, io->base_bio, io->base_bio, ++ io->sector); + +- r = crypt_convert(cc, &io->ctx, +- test_bit(DM_CRYPT_NO_READ_WORKQUEUE, &cc->flags), true); ++ r = crypt_convert(cc, &io->ctx, ++ test_bit(DM_CRYPT_NO_READ_WORKQUEUE, &cc->flags), true); ++ } + /* + * Crypto API backlogged the request, because its queue was full + * and we're in softirq context, so continue from a workqueue +@@ -2182,10 +2242,13 @@ static void kcryptd_async_done(void *data, int error) + if (error == -EBADMSG) { + sector_t s = le64_to_cpu(*org_sector_of_dmreq(cc, dmreq)); + +- DMERR_LIMIT("%pg: INTEGRITY AEAD ERROR, sector %llu", +- ctx->bio_in->bi_bdev, s); +- dm_audit_log_bio(DM_MSG_PREFIX, "integrity-aead", +- ctx->bio_in, s, 0); ++ ctx->aead_failed = true; ++ if (ctx->aead_recheck) { ++ DMERR_LIMIT("%pg: INTEGRITY AEAD ERROR, sector %llu", ++ ctx->bio_in->bi_bdev, s); ++ dm_audit_log_bio(DM_MSG_PREFIX, "integrity-aead", ++ ctx->bio_in, s, 0); ++ } + io->error = BLK_STS_PROTECTION; + } else if (error < 0) + io->error = BLK_STS_IOERR; +@@ -3110,7 +3173,7 @@ static int crypt_ctr_optional(struct dm_target *ti, unsigned int argc, char **ar + sval = strchr(opt_string + strlen("integrity:"), ':') + 1; + if (!strcasecmp(sval, "aead")) { + set_bit(CRYPT_MODE_INTEGRITY_AEAD, &cc->cipher_flags); +- } else if (strcasecmp(sval, "none")) { ++ } else if (strcasecmp(sval, "none")) { + ti->error = "Unknown integrity profile"; + return -EINVAL; + } +diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c +index c5f03aab45525..e8e8fc33d3440 100644 +--- a/drivers/md/dm-integrity.c ++++ b/drivers/md/dm-integrity.c +@@ -278,6 +278,8 @@ struct dm_integrity_c { + + atomic64_t number_of_mismatches; + ++ mempool_t recheck_pool; ++ + struct notifier_block reboot_notifier; + }; + +@@ -1689,6 +1691,77 @@ static void integrity_sector_checksum(struct dm_integrity_c *ic, sector_t sector + get_random_bytes(result, ic->tag_size); + } + ++static noinline void integrity_recheck(struct dm_integrity_io *dio, char *checksum) ++{ ++ struct bio *bio = dm_bio_from_per_bio_data(dio, sizeof(struct dm_integrity_io)); ++ struct dm_integrity_c *ic = dio->ic; ++ struct bvec_iter iter; ++ struct bio_vec bv; ++ sector_t sector, logical_sector, area, offset; ++ struct page *page; ++ void *buffer; ++ ++ get_area_and_offset(ic, dio->range.logical_sector, &area, &offset); ++ dio->metadata_block = get_metadata_sector_and_offset(ic, area, offset, ++ &dio->metadata_offset); ++ sector = get_data_sector(ic, area, offset); ++ logical_sector = dio->range.logical_sector; ++ ++ page = mempool_alloc(&ic->recheck_pool, GFP_NOIO); ++ buffer = page_to_virt(page); ++ ++ __bio_for_each_segment(bv, bio, iter, dio->bio_details.bi_iter) { ++ unsigned pos = 0; ++ ++ do { ++ char *mem; ++ int r; ++ struct dm_io_request io_req; ++ struct dm_io_region io_loc; ++ io_req.bi_opf = REQ_OP_READ; ++ io_req.mem.type = DM_IO_KMEM; ++ io_req.mem.ptr.addr = buffer; ++ io_req.notify.fn = NULL; ++ io_req.client = ic->io; ++ io_loc.bdev = ic->dev->bdev; ++ io_loc.sector = sector; ++ io_loc.count = ic->sectors_per_block; ++ ++ r = dm_io(&io_req, 1, &io_loc, NULL); ++ if (unlikely(r)) { ++ dio->bi_status = errno_to_blk_status(r); ++ goto free_ret; ++ } ++ ++ integrity_sector_checksum(ic, logical_sector, buffer, checksum); ++ r = dm_integrity_rw_tag(ic, checksum, &dio->metadata_block, ++ &dio->metadata_offset, ic->tag_size, TAG_CMP); ++ if (r) { ++ if (r > 0) { ++ DMERR_LIMIT("%pg: Checksum failed at sector 0x%llx", ++ bio->bi_bdev, logical_sector); ++ atomic64_inc(&ic->number_of_mismatches); ++ dm_audit_log_bio(DM_MSG_PREFIX, "integrity-checksum", ++ bio, logical_sector, 0); ++ r = -EILSEQ; ++ } ++ dio->bi_status = errno_to_blk_status(r); ++ goto free_ret; ++ } ++ ++ mem = bvec_kmap_local(&bv); ++ memcpy(mem + pos, buffer, ic->sectors_per_block << SECTOR_SHIFT); ++ kunmap_local(mem); ++ ++ pos += ic->sectors_per_block << SECTOR_SHIFT; ++ sector += ic->sectors_per_block; ++ logical_sector += ic->sectors_per_block; ++ } while (pos < bv.bv_len); ++ } ++free_ret: ++ mempool_free(page, &ic->recheck_pool); ++} ++ + static void integrity_metadata(struct work_struct *w) + { + struct dm_integrity_io *dio = container_of(w, struct dm_integrity_io, work); +@@ -1776,15 +1849,8 @@ static void integrity_metadata(struct work_struct *w) + checksums_ptr - checksums, dio->op == REQ_OP_READ ? TAG_CMP : TAG_WRITE); + if (unlikely(r)) { + if (r > 0) { +- sector_t s; +- +- s = sector - ((r + ic->tag_size - 1) / ic->tag_size); +- DMERR_LIMIT("%pg: Checksum failed at sector 0x%llx", +- bio->bi_bdev, s); +- r = -EILSEQ; +- atomic64_inc(&ic->number_of_mismatches); +- dm_audit_log_bio(DM_MSG_PREFIX, "integrity-checksum", +- bio, s, 0); ++ integrity_recheck(dio, checksums); ++ goto skip_io; + } + if (likely(checksums != checksums_onstack)) + kfree(checksums); +@@ -4261,6 +4327,12 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned int argc, char **argv + goto bad; + } + ++ r = mempool_init_page_pool(&ic->recheck_pool, 1, 0); ++ if (r) { ++ ti->error = "Cannot allocate mempool"; ++ goto bad; ++ } ++ + ic->metadata_wq = alloc_workqueue("dm-integrity-metadata", + WQ_MEM_RECLAIM, METADATA_WORKQUEUE_MAX_ACTIVE); + if (!ic->metadata_wq) { +@@ -4609,6 +4681,7 @@ static void dm_integrity_dtr(struct dm_target *ti) + kvfree(ic->bbs); + if (ic->bufio) + dm_bufio_client_destroy(ic->bufio); ++ mempool_exit(&ic->recheck_pool); + mempool_exit(&ic->journal_io_mempool); + if (ic->io) + dm_io_client_destroy(ic->io); +diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c +index 82662f5769c4a..7b620b187da90 100644 +--- a/drivers/md/dm-verity-target.c ++++ b/drivers/md/dm-verity-target.c +@@ -482,6 +482,63 @@ int verity_for_bv_block(struct dm_verity *v, struct dm_verity_io *io, + return 0; + } + ++static int verity_recheck_copy(struct dm_verity *v, struct dm_verity_io *io, ++ u8 *data, size_t len) ++{ ++ memcpy(data, io->recheck_buffer, len); ++ io->recheck_buffer += len; ++ ++ return 0; ++} ++ ++static noinline int verity_recheck(struct dm_verity *v, struct dm_verity_io *io, ++ struct bvec_iter start, sector_t cur_block) ++{ ++ struct page *page; ++ void *buffer; ++ int r; ++ struct dm_io_request io_req; ++ struct dm_io_region io_loc; ++ ++ page = mempool_alloc(&v->recheck_pool, GFP_NOIO); ++ buffer = page_to_virt(page); ++ ++ io_req.bi_opf = REQ_OP_READ; ++ io_req.mem.type = DM_IO_KMEM; ++ io_req.mem.ptr.addr = buffer; ++ io_req.notify.fn = NULL; ++ io_req.client = v->io; ++ io_loc.bdev = v->data_dev->bdev; ++ io_loc.sector = cur_block << (v->data_dev_block_bits - SECTOR_SHIFT); ++ io_loc.count = 1 << (v->data_dev_block_bits - SECTOR_SHIFT); ++ r = dm_io(&io_req, 1, &io_loc, NULL); ++ if (unlikely(r)) ++ goto free_ret; ++ ++ r = verity_hash(v, verity_io_hash_req(v, io), buffer, ++ 1 << v->data_dev_block_bits, ++ verity_io_real_digest(v, io), true); ++ if (unlikely(r)) ++ goto free_ret; ++ ++ if (memcmp(verity_io_real_digest(v, io), ++ verity_io_want_digest(v, io), v->digest_size)) { ++ r = -EIO; ++ goto free_ret; ++ } ++ ++ io->recheck_buffer = buffer; ++ r = verity_for_bv_block(v, io, &start, verity_recheck_copy); ++ if (unlikely(r)) ++ goto free_ret; ++ ++ r = 0; ++free_ret: ++ mempool_free(page, &v->recheck_pool); ++ ++ return r; ++} ++ + static int verity_bv_zero(struct dm_verity *v, struct dm_verity_io *io, + u8 *data, size_t len) + { +@@ -508,9 +565,7 @@ static int verity_verify_io(struct dm_verity_io *io) + { + bool is_zero; + struct dm_verity *v = io->v; +-#if defined(CONFIG_DM_VERITY_FEC) + struct bvec_iter start; +-#endif + struct bvec_iter iter_copy; + struct bvec_iter *iter; + struct crypto_wait wait; +@@ -561,10 +616,7 @@ static int verity_verify_io(struct dm_verity_io *io) + if (unlikely(r < 0)) + return r; + +-#if defined(CONFIG_DM_VERITY_FEC) +- if (verity_fec_is_enabled(v)) +- start = *iter; +-#endif ++ start = *iter; + r = verity_for_io_block(v, io, iter, &wait); + if (unlikely(r < 0)) + return r; +@@ -586,6 +638,10 @@ static int verity_verify_io(struct dm_verity_io *io) + * tasklet since it may sleep, so fallback to work-queue. + */ + return -EAGAIN; ++ } else if (verity_recheck(v, io, start, cur_block) == 0) { ++ if (v->validated_blocks) ++ set_bit(cur_block, v->validated_blocks); ++ continue; + #if defined(CONFIG_DM_VERITY_FEC) + } else if (verity_fec_decode(v, io, DM_VERITY_BLOCK_TYPE_DATA, + cur_block, NULL, &start) == 0) { +@@ -941,6 +997,10 @@ static void verity_dtr(struct dm_target *ti) + if (v->verify_wq) + destroy_workqueue(v->verify_wq); + ++ mempool_exit(&v->recheck_pool); ++ if (v->io) ++ dm_io_client_destroy(v->io); ++ + if (v->bufio) + dm_bufio_client_destroy(v->bufio); + +@@ -1379,6 +1439,20 @@ static int verity_ctr(struct dm_target *ti, unsigned int argc, char **argv) + } + v->hash_blocks = hash_position; + ++ r = mempool_init_page_pool(&v->recheck_pool, 1, 0); ++ if (unlikely(r)) { ++ ti->error = "Cannot allocate mempool"; ++ goto bad; ++ } ++ ++ v->io = dm_io_client_create(); ++ if (IS_ERR(v->io)) { ++ r = PTR_ERR(v->io); ++ v->io = NULL; ++ ti->error = "Cannot allocate dm io"; ++ goto bad; ++ } ++ + v->bufio = dm_bufio_client_create(v->hash_dev->bdev, + 1 << v->hash_dev_block_bits, 1, sizeof(struct buffer_aux), + dm_bufio_alloc_callback, NULL, +diff --git a/drivers/md/dm-verity.h b/drivers/md/dm-verity.h +index f3f6070084196..4620a98c99561 100644 +--- a/drivers/md/dm-verity.h ++++ b/drivers/md/dm-verity.h +@@ -11,6 +11,7 @@ + #ifndef DM_VERITY_H + #define DM_VERITY_H + ++#include <linux/dm-io.h> + #include <linux/dm-bufio.h> + #include <linux/device-mapper.h> + #include <linux/interrupt.h> +@@ -68,6 +69,9 @@ struct dm_verity { + unsigned long *validated_blocks; /* bitset blocks validated */ + + char *signature_key_desc; /* signature keyring reference */ ++ ++ struct dm_io_client *io; ++ mempool_t recheck_pool; + }; + + struct dm_verity_io { +@@ -84,6 +88,8 @@ struct dm_verity_io { + + struct work_struct work; + ++ char *recheck_buffer; ++ + /* + * Three variably-size fields follow this struct: + * +diff --git a/drivers/md/md.c b/drivers/md/md.c +index d243c196c5980..58889bc72659a 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -579,8 +579,12 @@ static void submit_flushes(struct work_struct *ws) + rcu_read_lock(); + } + rcu_read_unlock(); +- if (atomic_dec_and_test(&mddev->flush_pending)) ++ if (atomic_dec_and_test(&mddev->flush_pending)) { ++ /* The pair is percpu_ref_get() from md_flush_request() */ ++ percpu_ref_put(&mddev->active_io); ++ + queue_work(md_wq, &mddev->flush_work); ++ } + } + + static void md_submit_flush_data(struct work_struct *ws) +@@ -8813,12 +8817,16 @@ void md_do_sync(struct md_thread *thread) + int ret; + + /* just incase thread restarts... */ +- if (test_bit(MD_RECOVERY_DONE, &mddev->recovery) || +- test_bit(MD_RECOVERY_WAIT, &mddev->recovery)) ++ if (test_bit(MD_RECOVERY_DONE, &mddev->recovery)) + return; +- if (!md_is_rdwr(mddev)) {/* never try to sync a read-only array */ ++ ++ if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) ++ goto skip; ++ ++ if (test_bit(MD_RECOVERY_WAIT, &mddev->recovery) || ++ !md_is_rdwr(mddev)) {/* never try to sync a read-only array */ + set_bit(MD_RECOVERY_INTR, &mddev->recovery); +- return; ++ goto skip; + } + + if (mddev_is_clustered(mddev)) { +@@ -9418,13 +9426,19 @@ static void md_start_sync(struct work_struct *ws) + struct mddev *mddev = container_of(ws, struct mddev, sync_work); + int spares = 0; + bool suspend = false; ++ char *name; + +- if (md_spares_need_change(mddev)) ++ /* ++ * If reshape is still in progress, spares won't be added or removed ++ * from conf until reshape is done. ++ */ ++ if (mddev->reshape_position == MaxSector && ++ md_spares_need_change(mddev)) { + suspend = true; ++ mddev_suspend(mddev, false); ++ } + +- suspend ? mddev_suspend_and_lock_nointr(mddev) : +- mddev_lock_nointr(mddev); +- ++ mddev_lock_nointr(mddev); + if (!md_is_rdwr(mddev)) { + /* + * On a read-only array we can: +@@ -9450,8 +9464,10 @@ static void md_start_sync(struct work_struct *ws) + if (spares) + md_bitmap_write_all(mddev->bitmap); + ++ name = test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) ? ++ "reshape" : "resync"; + rcu_assign_pointer(mddev->sync_thread, +- md_register_thread(md_do_sync, mddev, "resync")); ++ md_register_thread(md_do_sync, mddev, name)); + if (!mddev->sync_thread) { + pr_warn("%s: could not start resync thread...\n", + mdname(mddev)); +@@ -9495,6 +9511,20 @@ static void md_start_sync(struct work_struct *ws) + sysfs_notify_dirent_safe(mddev->sysfs_action); + } + ++static void unregister_sync_thread(struct mddev *mddev) ++{ ++ if (!test_bit(MD_RECOVERY_DONE, &mddev->recovery)) { ++ /* resync/recovery still happening */ ++ clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery); ++ return; ++ } ++ ++ if (WARN_ON_ONCE(!mddev->sync_thread)) ++ return; ++ ++ md_reap_sync_thread(mddev); ++} ++ + /* + * This routine is regularly called by all per-raid-array threads to + * deal with generic issues like resync and super-block update. +@@ -9519,9 +9549,6 @@ static void md_start_sync(struct work_struct *ws) + */ + void md_check_recovery(struct mddev *mddev) + { +- if (READ_ONCE(mddev->suspended)) +- return; +- + if (mddev->bitmap) + md_bitmap_daemon_work(mddev); + +@@ -9535,7 +9562,8 @@ void md_check_recovery(struct mddev *mddev) + } + + if (!md_is_rdwr(mddev) && +- !test_bit(MD_RECOVERY_NEEDED, &mddev->recovery)) ++ !test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) && ++ !test_bit(MD_RECOVERY_DONE, &mddev->recovery)) + return; + if ( ! ( + (mddev->sb_flags & ~ (1<<MD_SB_CHANGE_PENDING)) || +@@ -9557,8 +9585,7 @@ void md_check_recovery(struct mddev *mddev) + struct md_rdev *rdev; + + if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) { +- /* sync_work already queued. */ +- clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery); ++ unregister_sync_thread(mddev); + goto unlock; + } + +@@ -9621,16 +9648,7 @@ void md_check_recovery(struct mddev *mddev) + * still set. + */ + if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) { +- if (!test_bit(MD_RECOVERY_DONE, &mddev->recovery)) { +- /* resync/recovery still happening */ +- clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery); +- goto unlock; +- } +- +- if (WARN_ON_ONCE(!mddev->sync_thread)) +- goto unlock; +- +- md_reap_sync_thread(mddev); ++ unregister_sync_thread(mddev); + goto unlock; + } + +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index a5927e98dc678..b7b0a573e7f8b 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -4307,11 +4307,7 @@ static int raid10_run(struct mddev *mddev) + clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); + clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); + set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); +- set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); +- rcu_assign_pointer(mddev->sync_thread, +- md_register_thread(md_do_sync, mddev, "reshape")); +- if (!mddev->sync_thread) +- goto out_free_conf; ++ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + } + + return 0; +@@ -4707,16 +4703,8 @@ static int raid10_start_reshape(struct mddev *mddev) + clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); + clear_bit(MD_RECOVERY_DONE, &mddev->recovery); + set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); +- set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); +- +- rcu_assign_pointer(mddev->sync_thread, +- md_register_thread(md_do_sync, mddev, "reshape")); +- if (!mddev->sync_thread) { +- ret = -EAGAIN; +- goto abort; +- } ++ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + conf->reshape_checkpoint = jiffies; +- md_wakeup_thread(mddev->sync_thread); + md_new_event(); + return 0; + +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index 26e1e8a5e9419..6fe334bb954ab 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -8002,11 +8002,7 @@ static int raid5_run(struct mddev *mddev) + clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); + clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); + set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); +- set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); +- rcu_assign_pointer(mddev->sync_thread, +- md_register_thread(md_do_sync, mddev, "reshape")); +- if (!mddev->sync_thread) +- goto abort; ++ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + } + + /* Ok, everything is just fine now */ +@@ -8585,29 +8581,8 @@ static int raid5_start_reshape(struct mddev *mddev) + clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); + clear_bit(MD_RECOVERY_DONE, &mddev->recovery); + set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); +- set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); +- rcu_assign_pointer(mddev->sync_thread, +- md_register_thread(md_do_sync, mddev, "reshape")); +- if (!mddev->sync_thread) { +- mddev->recovery = 0; +- spin_lock_irq(&conf->device_lock); +- write_seqcount_begin(&conf->gen_lock); +- mddev->raid_disks = conf->raid_disks = conf->previous_raid_disks; +- mddev->new_chunk_sectors = +- conf->chunk_sectors = conf->prev_chunk_sectors; +- mddev->new_layout = conf->algorithm = conf->prev_algo; +- rdev_for_each(rdev, mddev) +- rdev->new_data_offset = rdev->data_offset; +- smp_wmb(); +- conf->generation --; +- conf->reshape_progress = MaxSector; +- mddev->reshape_position = MaxSector; +- write_seqcount_end(&conf->gen_lock); +- spin_unlock_irq(&conf->device_lock); +- return -EAGAIN; +- } ++ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + conf->reshape_checkpoint = jiffies; +- md_wakeup_thread(mddev->sync_thread); + md_new_event(); + return 0; + } +diff --git a/drivers/misc/open-dice.c b/drivers/misc/open-dice.c +index 8aea2d070a40c..d279a4f195e2a 100644 +--- a/drivers/misc/open-dice.c ++++ b/drivers/misc/open-dice.c +@@ -140,7 +140,6 @@ static int __init open_dice_probe(struct platform_device *pdev) + return -ENOMEM; + + *drvdata = (struct open_dice_drvdata){ +- .lock = __MUTEX_INITIALIZER(drvdata->lock), + .rmem = rmem, + .misc = (struct miscdevice){ + .parent = dev, +@@ -150,6 +149,7 @@ static int __init open_dice_probe(struct platform_device *pdev) + .mode = 0600, + }, + }; ++ mutex_init(&drvdata->lock); + + /* Index overflow check not needed, misc_register() will fail. */ + snprintf(drvdata->name, sizeof(drvdata->name), DRIVER_NAME"%u", dev_idx++); +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +index 29b04a274d077..80245c65cc904 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp.c ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +@@ -535,9 +535,6 @@ int bcmasp_netfilt_get_all_active(struct bcmasp_intf *intf, u32 *rule_locs, + int j = 0, i; + + for (i = 0; i < NUM_NET_FILTERS; i++) { +- if (j == *rule_cnt) +- return -EMSGSIZE; +- + if (!priv->net_filters[i].claimed || + priv->net_filters[i].port != intf->port) + continue; +@@ -547,6 +544,9 @@ int bcmasp_netfilt_get_all_active(struct bcmasp_intf *intf, u32 *rule_locs, + priv->net_filters[i - 1].wake_filter) + continue; + ++ if (j == *rule_cnt) ++ return -EMSGSIZE; ++ + rule_locs[j++] = priv->net_filters[i].fs.location; + } + +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c +index 53e5428812552..9cae5a3090000 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c +@@ -1048,6 +1048,9 @@ static int bcmasp_netif_init(struct net_device *dev, bool phy_connect) + netdev_err(dev, "could not attach to PHY\n"); + goto err_phy_disable; + } ++ ++ /* Indicate that the MAC is responsible for PHY PM */ ++ phydev->mac_managed_pm = true; + } else if (!intf->wolopts) { + ret = phy_resume(dev->phydev); + if (ret) +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +index 3784347b6fd88..55639c133dd02 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +@@ -437,6 +437,10 @@ static void npc_fixup_vf_rule(struct rvu *rvu, struct npc_mcam *mcam, + return; + } + ++ /* AF modifies given action iff PF/VF has requested for it */ ++ if ((entry->action & 0xFULL) != NIX_RX_ACTION_DEFAULT) ++ return; ++ + /* copy VF default entry action to the VF mcam entry */ + rx_action = npc_get_default_entry_action(rvu, mcam, blkaddr, + target_func); +diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c +index d1f7fc8b1b71a..3c066b62e6894 100644 +--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c +@@ -757,6 +757,7 @@ static int mchp_sparx5_probe(struct platform_device *pdev) + platform_set_drvdata(pdev, sparx5); + sparx5->pdev = pdev; + sparx5->dev = &pdev->dev; ++ spin_lock_init(&sparx5->tx_lock); + + /* Do switch core reset if available */ + reset = devm_reset_control_get_optional_shared(&pdev->dev, "switch"); +diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h +index 6f565c0c0c3dc..316fed5f27355 100644 +--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h +@@ -280,6 +280,7 @@ struct sparx5 { + int xtr_irq; + /* Frame DMA */ + int fdma_irq; ++ spinlock_t tx_lock; /* lock for frame transmission */ + struct sparx5_rx rx; + struct sparx5_tx tx; + /* PTP */ +diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c b/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c +index 6db6ac6a3bbc2..ac7e1cffbcecf 100644 +--- a/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c +@@ -244,10 +244,12 @@ netdev_tx_t sparx5_port_xmit_impl(struct sk_buff *skb, struct net_device *dev) + } + + skb_tx_timestamp(skb); ++ spin_lock(&sparx5->tx_lock); + if (sparx5->fdma_irq > 0) + ret = sparx5_fdma_xmit(sparx5, ifh, skb); + else + ret = sparx5_inject(sparx5, ifh, skb, dev); ++ spin_unlock(&sparx5->tx_lock); + + if (ret == -EBUSY) + goto busy; +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index ec34768e054da..e9a1b60ebb503 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -5977,11 +5977,6 @@ static irqreturn_t stmmac_mac_interrupt(int irq, void *dev_id) + struct net_device *dev = (struct net_device *)dev_id; + struct stmmac_priv *priv = netdev_priv(dev); + +- if (unlikely(!dev)) { +- netdev_err(priv->dev, "%s: invalid dev pointer\n", __func__); +- return IRQ_NONE; +- } +- + /* Check if adapter is up */ + if (test_bit(STMMAC_DOWN, &priv->state)) + return IRQ_HANDLED; +@@ -5997,11 +5992,6 @@ static irqreturn_t stmmac_safety_interrupt(int irq, void *dev_id) + struct net_device *dev = (struct net_device *)dev_id; + struct stmmac_priv *priv = netdev_priv(dev); + +- if (unlikely(!dev)) { +- netdev_err(priv->dev, "%s: invalid dev pointer\n", __func__); +- return IRQ_NONE; +- } +- + /* Check if adapter is up */ + if (test_bit(STMMAC_DOWN, &priv->state)) + return IRQ_HANDLED; +@@ -6023,11 +6013,6 @@ static irqreturn_t stmmac_msi_intr_tx(int irq, void *data) + dma_conf = container_of(tx_q, struct stmmac_dma_conf, tx_queue[chan]); + priv = container_of(dma_conf, struct stmmac_priv, dma_conf); + +- if (unlikely(!data)) { +- netdev_err(priv->dev, "%s: invalid dev pointer\n", __func__); +- return IRQ_NONE; +- } +- + /* Check if adapter is up */ + if (test_bit(STMMAC_DOWN, &priv->state)) + return IRQ_HANDLED; +@@ -6054,11 +6039,6 @@ static irqreturn_t stmmac_msi_intr_rx(int irq, void *data) + dma_conf = container_of(rx_q, struct stmmac_dma_conf, rx_queue[chan]); + priv = container_of(dma_conf, struct stmmac_priv, dma_conf); + +- if (unlikely(!data)) { +- netdev_err(priv->dev, "%s: invalid dev pointer\n", __func__); +- return IRQ_NONE; +- } +- + /* Check if adapter is up */ + if (test_bit(STMMAC_DOWN, &priv->state)) + return IRQ_HANDLED; +diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c +index b1919278e931f..2129ae42c7030 100644 +--- a/drivers/net/gtp.c ++++ b/drivers/net/gtp.c +@@ -1907,20 +1907,20 @@ static int __init gtp_init(void) + if (err < 0) + goto error_out; + +- err = genl_register_family(>p_genl_family); ++ err = register_pernet_subsys(>p_net_ops); + if (err < 0) + goto unreg_rtnl_link; + +- err = register_pernet_subsys(>p_net_ops); ++ err = genl_register_family(>p_genl_family); + if (err < 0) +- goto unreg_genl_family; ++ goto unreg_pernet_subsys; + + pr_info("GTP module loaded (pdp ctx size %zd bytes)\n", + sizeof(struct pdp_ctx)); + return 0; + +-unreg_genl_family: +- genl_unregister_family(>p_genl_family); ++unreg_pernet_subsys: ++ unregister_pernet_subsys(>p_net_ops); + unreg_rtnl_link: + rtnl_link_unregister(>p_link_ops); + error_out: +diff --git a/drivers/net/ipa/ipa_interrupt.c b/drivers/net/ipa/ipa_interrupt.c +index 4bc05948f772d..a78c692f2d3c5 100644 +--- a/drivers/net/ipa/ipa_interrupt.c ++++ b/drivers/net/ipa/ipa_interrupt.c +@@ -212,7 +212,7 @@ void ipa_interrupt_suspend_clear_all(struct ipa_interrupt *interrupt) + u32 unit_count; + u32 unit; + +- unit_count = roundup(ipa->endpoint_count, 32); ++ unit_count = DIV_ROUND_UP(ipa->endpoint_count, 32); + for (unit = 0; unit < unit_count; unit++) { + const struct reg *reg; + u32 val; +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index 894172a3e15fe..337899c69738e 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -421,9 +421,11 @@ static int rtl8211f_config_init(struct phy_device *phydev) + ERR_PTR(ret)); + return ret; + } ++ ++ return genphy_soft_reset(phydev); + } + +- return genphy_soft_reset(phydev); ++ return 0; + } + + static int rtl821x_suspend(struct phy_device *phydev) +diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +index 480f8edbfd35d..678c4a071869f 100644 +--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c ++++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +@@ -668,7 +668,6 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = { + .has_eht = true, + .eht_cap_elem = { + .mac_cap_info[0] = +- IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS | + IEEE80211_EHT_MAC_CAP0_OM_CONTROL | + IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 | + IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2 | +@@ -793,7 +792,6 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = { + .has_eht = true, + .eht_cap_elem = { + .mac_cap_info[0] = +- IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS | + IEEE80211_EHT_MAC_CAP0_OM_CONTROL | + IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 | + IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2, +@@ -1020,8 +1018,7 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans, + if (CSR_HW_REV_TYPE(trans->hw_rev) == IWL_CFG_MAC_TYPE_GL && + iftype_data->eht_cap.has_eht) { + iftype_data->eht_cap.eht_cap_elem.mac_cap_info[0] &= +- ~(IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS | +- IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 | ++ ~(IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 | + IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2); + iftype_data->eht_cap.eht_cap_elem.phy_cap_info[3] &= + ~(IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO | +diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c +index 1d51925ea67fd..e0f4129c3a8ed 100644 +--- a/drivers/nvme/host/fc.c ++++ b/drivers/nvme/host/fc.c +@@ -221,11 +221,6 @@ static LIST_HEAD(nvme_fc_lport_list); + static DEFINE_IDA(nvme_fc_local_port_cnt); + static DEFINE_IDA(nvme_fc_ctrl_cnt); + +-static struct workqueue_struct *nvme_fc_wq; +- +-static bool nvme_fc_waiting_to_unload; +-static DECLARE_COMPLETION(nvme_fc_unload_proceed); +- + /* + * These items are short-term. They will eventually be moved into + * a generic FC class. See comments in module init. +@@ -255,8 +250,6 @@ nvme_fc_free_lport(struct kref *ref) + /* remove from transport list */ + spin_lock_irqsave(&nvme_fc_lock, flags); + list_del(&lport->port_list); +- if (nvme_fc_waiting_to_unload && list_empty(&nvme_fc_lport_list)) +- complete(&nvme_fc_unload_proceed); + spin_unlock_irqrestore(&nvme_fc_lock, flags); + + ida_free(&nvme_fc_local_port_cnt, lport->localport.port_num); +@@ -3896,10 +3889,6 @@ static int __init nvme_fc_init_module(void) + { + int ret; + +- nvme_fc_wq = alloc_workqueue("nvme_fc_wq", WQ_MEM_RECLAIM, 0); +- if (!nvme_fc_wq) +- return -ENOMEM; +- + /* + * NOTE: + * It is expected that in the future the kernel will combine +@@ -3917,7 +3906,7 @@ static int __init nvme_fc_init_module(void) + ret = class_register(&fc_class); + if (ret) { + pr_err("couldn't register class fc\n"); +- goto out_destroy_wq; ++ return ret; + } + + /* +@@ -3941,8 +3930,6 @@ static int __init nvme_fc_init_module(void) + device_destroy(&fc_class, MKDEV(0, 0)); + out_destroy_class: + class_unregister(&fc_class); +-out_destroy_wq: +- destroy_workqueue(nvme_fc_wq); + + return ret; + } +@@ -3962,45 +3949,23 @@ nvme_fc_delete_controllers(struct nvme_fc_rport *rport) + spin_unlock(&rport->lock); + } + +-static void +-nvme_fc_cleanup_for_unload(void) ++static void __exit nvme_fc_exit_module(void) + { + struct nvme_fc_lport *lport; + struct nvme_fc_rport *rport; +- +- list_for_each_entry(lport, &nvme_fc_lport_list, port_list) { +- list_for_each_entry(rport, &lport->endp_list, endp_list) { +- nvme_fc_delete_controllers(rport); +- } +- } +-} +- +-static void __exit nvme_fc_exit_module(void) +-{ + unsigned long flags; +- bool need_cleanup = false; + + spin_lock_irqsave(&nvme_fc_lock, flags); +- nvme_fc_waiting_to_unload = true; +- if (!list_empty(&nvme_fc_lport_list)) { +- need_cleanup = true; +- nvme_fc_cleanup_for_unload(); +- } ++ list_for_each_entry(lport, &nvme_fc_lport_list, port_list) ++ list_for_each_entry(rport, &lport->endp_list, endp_list) ++ nvme_fc_delete_controllers(rport); + spin_unlock_irqrestore(&nvme_fc_lock, flags); +- if (need_cleanup) { +- pr_info("%s: waiting for ctlr deletes\n", __func__); +- wait_for_completion(&nvme_fc_unload_proceed); +- pr_info("%s: ctrl deletes complete\n", __func__); +- } ++ flush_workqueue(nvme_delete_wq); + + nvmf_unregister_transport(&nvme_fc_transport); + +- ida_destroy(&nvme_fc_local_port_cnt); +- ida_destroy(&nvme_fc_ctrl_cnt); +- + device_destroy(&fc_class, MKDEV(0, 0)); + class_unregister(&fc_class); +- destroy_workqueue(nvme_fc_wq); + } + + module_init(nvme_fc_init_module); +diff --git a/drivers/nvme/target/fc.c b/drivers/nvme/target/fc.c +index bd59990b52501..666130878ee0f 100644 +--- a/drivers/nvme/target/fc.c ++++ b/drivers/nvme/target/fc.c +@@ -111,6 +111,8 @@ struct nvmet_fc_tgtport { + struct nvmet_fc_port_entry *pe; + struct kref ref; + u32 max_sg_cnt; ++ ++ struct work_struct put_work; + }; + + struct nvmet_fc_port_entry { +@@ -145,7 +147,6 @@ struct nvmet_fc_tgt_queue { + struct list_head avail_defer_list; + struct workqueue_struct *work_q; + struct kref ref; +- struct rcu_head rcu; + /* array of fcp_iods */ + struct nvmet_fc_fcp_iod fod[] __counted_by(sqsize); + } __aligned(sizeof(unsigned long long)); +@@ -166,10 +167,9 @@ struct nvmet_fc_tgt_assoc { + struct nvmet_fc_hostport *hostport; + struct nvmet_fc_ls_iod *rcv_disconn; + struct list_head a_list; +- struct nvmet_fc_tgt_queue __rcu *queues[NVMET_NR_QUEUES + 1]; ++ struct nvmet_fc_tgt_queue *queues[NVMET_NR_QUEUES + 1]; + struct kref ref; + struct work_struct del_work; +- struct rcu_head rcu; + }; + + +@@ -249,6 +249,13 @@ static int nvmet_fc_tgt_a_get(struct nvmet_fc_tgt_assoc *assoc); + static void nvmet_fc_tgt_q_put(struct nvmet_fc_tgt_queue *queue); + static int nvmet_fc_tgt_q_get(struct nvmet_fc_tgt_queue *queue); + static void nvmet_fc_tgtport_put(struct nvmet_fc_tgtport *tgtport); ++static void nvmet_fc_put_tgtport_work(struct work_struct *work) ++{ ++ struct nvmet_fc_tgtport *tgtport = ++ container_of(work, struct nvmet_fc_tgtport, put_work); ++ ++ nvmet_fc_tgtport_put(tgtport); ++} + static int nvmet_fc_tgtport_get(struct nvmet_fc_tgtport *tgtport); + static void nvmet_fc_handle_fcp_rqst(struct nvmet_fc_tgtport *tgtport, + struct nvmet_fc_fcp_iod *fod); +@@ -360,7 +367,7 @@ __nvmet_fc_finish_ls_req(struct nvmet_fc_ls_req_op *lsop) + + if (!lsop->req_queued) { + spin_unlock_irqrestore(&tgtport->lock, flags); +- return; ++ goto out_putwork; + } + + list_del(&lsop->lsreq_list); +@@ -373,7 +380,8 @@ __nvmet_fc_finish_ls_req(struct nvmet_fc_ls_req_op *lsop) + (lsreq->rqstlen + lsreq->rsplen), + DMA_BIDIRECTIONAL); + +- nvmet_fc_tgtport_put(tgtport); ++out_putwork: ++ queue_work(nvmet_wq, &tgtport->put_work); + } + + static int +@@ -802,14 +810,11 @@ nvmet_fc_alloc_target_queue(struct nvmet_fc_tgt_assoc *assoc, + if (!queue) + return NULL; + +- if (!nvmet_fc_tgt_a_get(assoc)) +- goto out_free_queue; +- + queue->work_q = alloc_workqueue("ntfc%d.%d.%d", 0, 0, + assoc->tgtport->fc_target_port.port_num, + assoc->a_id, qid); + if (!queue->work_q) +- goto out_a_put; ++ goto out_free_queue; + + queue->qid = qid; + queue->sqsize = sqsize; +@@ -831,15 +836,13 @@ nvmet_fc_alloc_target_queue(struct nvmet_fc_tgt_assoc *assoc, + goto out_fail_iodlist; + + WARN_ON(assoc->queues[qid]); +- rcu_assign_pointer(assoc->queues[qid], queue); ++ assoc->queues[qid] = queue; + + return queue; + + out_fail_iodlist: + nvmet_fc_destroy_fcp_iodlist(assoc->tgtport, queue); + destroy_workqueue(queue->work_q); +-out_a_put: +- nvmet_fc_tgt_a_put(assoc); + out_free_queue: + kfree(queue); + return NULL; +@@ -852,15 +855,11 @@ nvmet_fc_tgt_queue_free(struct kref *ref) + struct nvmet_fc_tgt_queue *queue = + container_of(ref, struct nvmet_fc_tgt_queue, ref); + +- rcu_assign_pointer(queue->assoc->queues[queue->qid], NULL); +- + nvmet_fc_destroy_fcp_iodlist(queue->assoc->tgtport, queue); + +- nvmet_fc_tgt_a_put(queue->assoc); +- + destroy_workqueue(queue->work_q); + +- kfree_rcu(queue, rcu); ++ kfree(queue); + } + + static void +@@ -969,7 +968,7 @@ nvmet_fc_find_target_queue(struct nvmet_fc_tgtport *tgtport, + rcu_read_lock(); + list_for_each_entry_rcu(assoc, &tgtport->assoc_list, a_list) { + if (association_id == assoc->association_id) { +- queue = rcu_dereference(assoc->queues[qid]); ++ queue = assoc->queues[qid]; + if (queue && + (!atomic_read(&queue->connected) || + !nvmet_fc_tgt_q_get(queue))) +@@ -1078,8 +1077,6 @@ nvmet_fc_alloc_hostport(struct nvmet_fc_tgtport *tgtport, void *hosthandle) + /* new allocation not needed */ + kfree(newhost); + newhost = match; +- /* no new allocation - release reference */ +- nvmet_fc_tgtport_put(tgtport); + } else { + newhost->tgtport = tgtport; + newhost->hosthandle = hosthandle; +@@ -1094,13 +1091,28 @@ nvmet_fc_alloc_hostport(struct nvmet_fc_tgtport *tgtport, void *hosthandle) + } + + static void +-nvmet_fc_delete_assoc(struct work_struct *work) ++nvmet_fc_delete_assoc(struct nvmet_fc_tgt_assoc *assoc) ++{ ++ nvmet_fc_delete_target_assoc(assoc); ++ nvmet_fc_tgt_a_put(assoc); ++} ++ ++static void ++nvmet_fc_delete_assoc_work(struct work_struct *work) + { + struct nvmet_fc_tgt_assoc *assoc = + container_of(work, struct nvmet_fc_tgt_assoc, del_work); ++ struct nvmet_fc_tgtport *tgtport = assoc->tgtport; + +- nvmet_fc_delete_target_assoc(assoc); +- nvmet_fc_tgt_a_put(assoc); ++ nvmet_fc_delete_assoc(assoc); ++ nvmet_fc_tgtport_put(tgtport); ++} ++ ++static void ++nvmet_fc_schedule_delete_assoc(struct nvmet_fc_tgt_assoc *assoc) ++{ ++ nvmet_fc_tgtport_get(assoc->tgtport); ++ queue_work(nvmet_wq, &assoc->del_work); + } + + static struct nvmet_fc_tgt_assoc * +@@ -1112,6 +1124,9 @@ nvmet_fc_alloc_target_assoc(struct nvmet_fc_tgtport *tgtport, void *hosthandle) + int idx; + bool needrandom = true; + ++ if (!tgtport->pe) ++ return NULL; ++ + assoc = kzalloc(sizeof(*assoc), GFP_KERNEL); + if (!assoc) + return NULL; +@@ -1131,7 +1146,7 @@ nvmet_fc_alloc_target_assoc(struct nvmet_fc_tgtport *tgtport, void *hosthandle) + assoc->a_id = idx; + INIT_LIST_HEAD(&assoc->a_list); + kref_init(&assoc->ref); +- INIT_WORK(&assoc->del_work, nvmet_fc_delete_assoc); ++ INIT_WORK(&assoc->del_work, nvmet_fc_delete_assoc_work); + atomic_set(&assoc->terminating, 0); + + while (needrandom) { +@@ -1172,13 +1187,18 @@ nvmet_fc_target_assoc_free(struct kref *ref) + struct nvmet_fc_tgtport *tgtport = assoc->tgtport; + struct nvmet_fc_ls_iod *oldls; + unsigned long flags; ++ int i; ++ ++ for (i = NVMET_NR_QUEUES; i >= 0; i--) { ++ if (assoc->queues[i]) ++ nvmet_fc_delete_target_queue(assoc->queues[i]); ++ } + + /* Send Disconnect now that all i/o has completed */ + nvmet_fc_xmt_disconnect_assoc(assoc); + + nvmet_fc_free_hostport(assoc->hostport); + spin_lock_irqsave(&tgtport->lock, flags); +- list_del_rcu(&assoc->a_list); + oldls = assoc->rcv_disconn; + spin_unlock_irqrestore(&tgtport->lock, flags); + /* if pending Rcv Disconnect Association LS, send rsp now */ +@@ -1188,8 +1208,8 @@ nvmet_fc_target_assoc_free(struct kref *ref) + dev_info(tgtport->dev, + "{%d:%d} Association freed\n", + tgtport->fc_target_port.port_num, assoc->a_id); +- kfree_rcu(assoc, rcu); + nvmet_fc_tgtport_put(tgtport); ++ kfree(assoc); + } + + static void +@@ -1208,7 +1228,7 @@ static void + nvmet_fc_delete_target_assoc(struct nvmet_fc_tgt_assoc *assoc) + { + struct nvmet_fc_tgtport *tgtport = assoc->tgtport; +- struct nvmet_fc_tgt_queue *queue; ++ unsigned long flags; + int i, terminating; + + terminating = atomic_xchg(&assoc->terminating, 1); +@@ -1217,29 +1237,21 @@ nvmet_fc_delete_target_assoc(struct nvmet_fc_tgt_assoc *assoc) + if (terminating) + return; + ++ spin_lock_irqsave(&tgtport->lock, flags); ++ list_del_rcu(&assoc->a_list); ++ spin_unlock_irqrestore(&tgtport->lock, flags); + +- for (i = NVMET_NR_QUEUES; i >= 0; i--) { +- rcu_read_lock(); +- queue = rcu_dereference(assoc->queues[i]); +- if (!queue) { +- rcu_read_unlock(); +- continue; +- } ++ synchronize_rcu(); + +- if (!nvmet_fc_tgt_q_get(queue)) { +- rcu_read_unlock(); +- continue; +- } +- rcu_read_unlock(); +- nvmet_fc_delete_target_queue(queue); +- nvmet_fc_tgt_q_put(queue); ++ /* ensure all in-flight I/Os have been processed */ ++ for (i = NVMET_NR_QUEUES; i >= 0; i--) { ++ if (assoc->queues[i]) ++ flush_workqueue(assoc->queues[i]->work_q); + } + + dev_info(tgtport->dev, + "{%d:%d} Association deleted\n", + tgtport->fc_target_port.port_num, assoc->a_id); +- +- nvmet_fc_tgt_a_put(assoc); + } + + static struct nvmet_fc_tgt_assoc * +@@ -1415,6 +1427,7 @@ nvmet_fc_register_targetport(struct nvmet_fc_port_info *pinfo, + kref_init(&newrec->ref); + ida_init(&newrec->assoc_cnt); + newrec->max_sg_cnt = template->max_sgl_segments; ++ INIT_WORK(&newrec->put_work, nvmet_fc_put_tgtport_work); + + ret = nvmet_fc_alloc_ls_iodlist(newrec); + if (ret) { +@@ -1492,9 +1505,8 @@ __nvmet_fc_free_assocs(struct nvmet_fc_tgtport *tgtport) + list_for_each_entry_rcu(assoc, &tgtport->assoc_list, a_list) { + if (!nvmet_fc_tgt_a_get(assoc)) + continue; +- if (!queue_work(nvmet_wq, &assoc->del_work)) +- /* already deleting - release local reference */ +- nvmet_fc_tgt_a_put(assoc); ++ nvmet_fc_schedule_delete_assoc(assoc); ++ nvmet_fc_tgt_a_put(assoc); + } + rcu_read_unlock(); + } +@@ -1547,9 +1559,8 @@ nvmet_fc_invalidate_host(struct nvmet_fc_target_port *target_port, + continue; + assoc->hostport->invalid = 1; + noassoc = false; +- if (!queue_work(nvmet_wq, &assoc->del_work)) +- /* already deleting - release local reference */ +- nvmet_fc_tgt_a_put(assoc); ++ nvmet_fc_schedule_delete_assoc(assoc); ++ nvmet_fc_tgt_a_put(assoc); + } + spin_unlock_irqrestore(&tgtport->lock, flags); + +@@ -1581,7 +1592,7 @@ nvmet_fc_delete_ctrl(struct nvmet_ctrl *ctrl) + + rcu_read_lock(); + list_for_each_entry_rcu(assoc, &tgtport->assoc_list, a_list) { +- queue = rcu_dereference(assoc->queues[0]); ++ queue = assoc->queues[0]; + if (queue && queue->nvme_sq.ctrl == ctrl) { + if (nvmet_fc_tgt_a_get(assoc)) + found_ctrl = true; +@@ -1593,9 +1604,8 @@ nvmet_fc_delete_ctrl(struct nvmet_ctrl *ctrl) + nvmet_fc_tgtport_put(tgtport); + + if (found_ctrl) { +- if (!queue_work(nvmet_wq, &assoc->del_work)) +- /* already deleting - release local reference */ +- nvmet_fc_tgt_a_put(assoc); ++ nvmet_fc_schedule_delete_assoc(assoc); ++ nvmet_fc_tgt_a_put(assoc); + return; + } + +@@ -1625,6 +1635,8 @@ nvmet_fc_unregister_targetport(struct nvmet_fc_target_port *target_port) + /* terminate any outstanding associations */ + __nvmet_fc_free_assocs(tgtport); + ++ flush_workqueue(nvmet_wq); ++ + /* + * should terminate LS's as well. However, LS's will be generated + * at the tail end of association termination, so they likely don't +@@ -1870,9 +1882,6 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport, + sizeof(struct fcnvme_ls_disconnect_assoc_acc)), + FCNVME_LS_DISCONNECT_ASSOC); + +- /* release get taken in nvmet_fc_find_target_assoc */ +- nvmet_fc_tgt_a_put(assoc); +- + /* + * The rules for LS response says the response cannot + * go back until ABTS's have been sent for all outstanding +@@ -1887,8 +1896,6 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport, + assoc->rcv_disconn = iod; + spin_unlock_irqrestore(&tgtport->lock, flags); + +- nvmet_fc_delete_target_assoc(assoc); +- + if (oldls) { + dev_info(tgtport->dev, + "{%d:%d} Multiple Disconnect Association LS's " +@@ -1904,6 +1911,9 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport, + nvmet_fc_xmt_ls_rsp(tgtport, oldls); + } + ++ nvmet_fc_schedule_delete_assoc(assoc); ++ nvmet_fc_tgt_a_put(assoc); ++ + return false; + } + +@@ -2540,8 +2550,9 @@ nvmet_fc_handle_fcp_rqst(struct nvmet_fc_tgtport *tgtport, + + fod->req.cmd = &fod->cmdiubuf.sqe; + fod->req.cqe = &fod->rspiubuf.cqe; +- if (tgtport->pe) +- fod->req.port = tgtport->pe->port; ++ if (!tgtport->pe) ++ goto transport_error; ++ fod->req.port = tgtport->pe->port; + + /* clear any response payload */ + memset(&fod->rspiubuf, 0, sizeof(fod->rspiubuf)); +@@ -2902,6 +2913,9 @@ nvmet_fc_remove_port(struct nvmet_port *port) + + nvmet_fc_portentry_unbind(pe); + ++ /* terminate any outstanding associations */ ++ __nvmet_fc_free_assocs(pe->tgtport); ++ + kfree(pe); + } + +@@ -2933,6 +2947,9 @@ static int __init nvmet_fc_init_module(void) + + static void __exit nvmet_fc_exit_module(void) + { ++ /* ensure any shutdown operation, e.g. delete ctrls have finished */ ++ flush_workqueue(nvmet_wq); ++ + /* sanity check - all lports should be removed */ + if (!list_empty(&nvmet_fc_target_list)) + pr_warn("%s: targetport list not empty\n", __func__); +diff --git a/drivers/nvme/target/fcloop.c b/drivers/nvme/target/fcloop.c +index c65a73433c05f..e6d4226827b52 100644 +--- a/drivers/nvme/target/fcloop.c ++++ b/drivers/nvme/target/fcloop.c +@@ -358,7 +358,7 @@ fcloop_h2t_ls_req(struct nvme_fc_local_port *localport, + if (!rport->targetport) { + tls_req->status = -ECONNREFUSED; + spin_lock(&rport->lock); +- list_add_tail(&rport->ls_list, &tls_req->ls_list); ++ list_add_tail(&tls_req->ls_list, &rport->ls_list); + spin_unlock(&rport->lock); + queue_work(nvmet_wq, &rport->ls_work); + return ret; +@@ -391,7 +391,7 @@ fcloop_h2t_xmt_ls_rsp(struct nvmet_fc_target_port *targetport, + if (remoteport) { + rport = remoteport->private; + spin_lock(&rport->lock); +- list_add_tail(&rport->ls_list, &tls_req->ls_list); ++ list_add_tail(&tls_req->ls_list, &rport->ls_list); + spin_unlock(&rport->lock); + queue_work(nvmet_wq, &rport->ls_work); + } +@@ -446,7 +446,7 @@ fcloop_t2h_ls_req(struct nvmet_fc_target_port *targetport, void *hosthandle, + if (!tport->remoteport) { + tls_req->status = -ECONNREFUSED; + spin_lock(&tport->lock); +- list_add_tail(&tport->ls_list, &tls_req->ls_list); ++ list_add_tail(&tls_req->ls_list, &tport->ls_list); + spin_unlock(&tport->lock); + queue_work(nvmet_wq, &tport->ls_work); + return ret; +diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c +index 80db64a4b09f6..bb42ae42b1c6e 100644 +--- a/drivers/nvme/target/tcp.c ++++ b/drivers/nvme/target/tcp.c +@@ -2204,6 +2204,7 @@ static void __exit nvmet_tcp_exit(void) + flush_workqueue(nvmet_wq); + + destroy_workqueue(nvmet_tcp_wq); ++ ida_destroy(&nvmet_tcp_queue_ida); + } + + module_init(nvmet_tcp_init); +diff --git a/drivers/pci/msi/irqdomain.c b/drivers/pci/msi/irqdomain.c +index c8be056c248de..cfd84a899c82d 100644 +--- a/drivers/pci/msi/irqdomain.c ++++ b/drivers/pci/msi/irqdomain.c +@@ -61,7 +61,7 @@ static irq_hw_number_t pci_msi_domain_calc_hwirq(struct msi_desc *desc) + + return (irq_hw_number_t)desc->msi_index | + pci_dev_id(dev) << 11 | +- (pci_domain_nr(dev->bus) & 0xFFFFFFFF) << 27; ++ ((irq_hw_number_t)(pci_domain_nr(dev->bus) & 0xFFFFFFFF)) << 27; + } + + static void pci_msi_domain_set_desc(msi_alloc_info_t *arg, +diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c +index 5c683b4eaf10a..f39b7b9d2bfea 100644 +--- a/drivers/platform/mellanox/mlxbf-tmfifo.c ++++ b/drivers/platform/mellanox/mlxbf-tmfifo.c +@@ -47,6 +47,9 @@ + /* Message with data needs at least two words (for header & data). */ + #define MLXBF_TMFIFO_DATA_MIN_WORDS 2 + ++/* Tx timeout in milliseconds. */ ++#define TMFIFO_TX_TIMEOUT 2000 ++ + /* ACPI UID for BlueField-3. */ + #define TMFIFO_BF3_UID 1 + +@@ -62,12 +65,14 @@ struct mlxbf_tmfifo; + * @drop_desc: dummy desc for packet dropping + * @cur_len: processed length of the current descriptor + * @rem_len: remaining length of the pending packet ++ * @rem_padding: remaining bytes to send as paddings + * @pkt_len: total length of the pending packet + * @next_avail: next avail descriptor id + * @num: vring size (number of descriptors) + * @align: vring alignment size + * @index: vring index + * @vdev_id: vring virtio id (VIRTIO_ID_xxx) ++ * @tx_timeout: expire time of last tx packet + * @fifo: pointer to the tmfifo structure + */ + struct mlxbf_tmfifo_vring { +@@ -79,12 +84,14 @@ struct mlxbf_tmfifo_vring { + struct vring_desc drop_desc; + int cur_len; + int rem_len; ++ int rem_padding; + u32 pkt_len; + u16 next_avail; + int num; + int align; + int index; + int vdev_id; ++ unsigned long tx_timeout; + struct mlxbf_tmfifo *fifo; + }; + +@@ -819,6 +826,50 @@ static bool mlxbf_tmfifo_rxtx_one_desc(struct mlxbf_tmfifo_vring *vring, + return true; + } + ++static void mlxbf_tmfifo_check_tx_timeout(struct mlxbf_tmfifo_vring *vring) ++{ ++ unsigned long flags; ++ ++ /* Only handle Tx timeout for network vdev. */ ++ if (vring->vdev_id != VIRTIO_ID_NET) ++ return; ++ ++ /* Initialize the timeout or return if not expired. */ ++ if (!vring->tx_timeout) { ++ /* Initialize the timeout. */ ++ vring->tx_timeout = jiffies + ++ msecs_to_jiffies(TMFIFO_TX_TIMEOUT); ++ return; ++ } else if (time_before(jiffies, vring->tx_timeout)) { ++ /* Return if not timeout yet. */ ++ return; ++ } ++ ++ /* ++ * Drop the packet after timeout. The outstanding packet is ++ * released and the remaining bytes will be sent with padding byte 0x00 ++ * as a recovery. On the peer(host) side, the padding bytes 0x00 will be ++ * either dropped directly, or appended into existing outstanding packet ++ * thus dropped as corrupted network packet. ++ */ ++ vring->rem_padding = round_up(vring->rem_len, sizeof(u64)); ++ mlxbf_tmfifo_release_pkt(vring); ++ vring->cur_len = 0; ++ vring->rem_len = 0; ++ vring->fifo->vring[0] = NULL; ++ ++ /* ++ * Make sure the load/store are in order before ++ * returning back to virtio. ++ */ ++ virtio_mb(false); ++ ++ /* Notify upper layer. */ ++ spin_lock_irqsave(&vring->fifo->spin_lock[0], flags); ++ vring_interrupt(0, vring->vq); ++ spin_unlock_irqrestore(&vring->fifo->spin_lock[0], flags); ++} ++ + /* Rx & Tx processing of a queue. */ + static void mlxbf_tmfifo_rxtx(struct mlxbf_tmfifo_vring *vring, bool is_rx) + { +@@ -841,6 +892,7 @@ static void mlxbf_tmfifo_rxtx(struct mlxbf_tmfifo_vring *vring, bool is_rx) + return; + + do { ++retry: + /* Get available FIFO space. */ + if (avail == 0) { + if (is_rx) +@@ -851,6 +903,17 @@ static void mlxbf_tmfifo_rxtx(struct mlxbf_tmfifo_vring *vring, bool is_rx) + break; + } + ++ /* Insert paddings for discarded Tx packet. */ ++ if (!is_rx) { ++ vring->tx_timeout = 0; ++ while (vring->rem_padding >= sizeof(u64)) { ++ writeq(0, vring->fifo->tx.data); ++ vring->rem_padding -= sizeof(u64); ++ if (--avail == 0) ++ goto retry; ++ } ++ } ++ + /* Console output always comes from the Tx buffer. */ + if (!is_rx && devid == VIRTIO_ID_CONSOLE) { + mlxbf_tmfifo_console_tx(fifo, avail); +@@ -860,6 +923,10 @@ static void mlxbf_tmfifo_rxtx(struct mlxbf_tmfifo_vring *vring, bool is_rx) + /* Handle one descriptor. */ + more = mlxbf_tmfifo_rxtx_one_desc(vring, is_rx, &avail); + } while (more); ++ ++ /* Check Tx timeout. */ ++ if (avail <= 0 && !is_rx) ++ mlxbf_tmfifo_check_tx_timeout(vring); + } + + /* Handle Rx or Tx queues. */ +diff --git a/drivers/platform/x86/intel/vbtn.c b/drivers/platform/x86/intel/vbtn.c +index 210b0a81b7ecb..084c355c86f5f 100644 +--- a/drivers/platform/x86/intel/vbtn.c ++++ b/drivers/platform/x86/intel/vbtn.c +@@ -200,9 +200,6 @@ static void notify_handler(acpi_handle handle, u32 event, void *context) + autorelease = val && (!ke_rel || ke_rel->type == KE_IGNORE); + + sparse_keymap_report_event(input_dev, event, val, autorelease); +- +- /* Some devices need this to report further events */ +- acpi_evaluate_object(handle, "VBDL", NULL, NULL); + } + + /* +diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c +index 3a396b763c496..ce3e08815a8e6 100644 +--- a/drivers/platform/x86/think-lmi.c ++++ b/drivers/platform/x86/think-lmi.c +@@ -1009,7 +1009,16 @@ static ssize_t current_value_store(struct kobject *kobj, + * Note - this sets the variable and then the password as separate + * WMI calls. Function tlmi_save_bios_settings will error if the + * password is incorrect. ++ * Workstation's require the opcode to be set before changing the ++ * attribute. + */ ++ if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) { ++ ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin", ++ tlmi_priv.pwd_admin->password); ++ if (ret) ++ goto out; ++ } ++ + set_str = kasprintf(GFP_KERNEL, "%s,%s;", setting->display_name, + new_setting); + if (!set_str) { +@@ -1021,17 +1030,10 @@ static ssize_t current_value_store(struct kobject *kobj, + if (ret) + goto out; + +- if (tlmi_priv.save_mode == TLMI_SAVE_BULK) { ++ if (tlmi_priv.save_mode == TLMI_SAVE_BULK) + tlmi_priv.save_required = true; +- } else { +- if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) { +- ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin", +- tlmi_priv.pwd_admin->password); +- if (ret) +- goto out; +- } ++ else + ret = tlmi_save_bios_settings(""); +- } + } else { /* old non-opcode based authentication method (deprecated) */ + if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) { + auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;", +diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c +index c4895e9bc7148..5ecd9d33250d7 100644 +--- a/drivers/platform/x86/thinkpad_acpi.c ++++ b/drivers/platform/x86/thinkpad_acpi.c +@@ -10308,6 +10308,7 @@ static int convert_dytc_to_profile(int funcmode, int dytcmode, + return 0; + default: + /* Unknown function */ ++ pr_debug("unknown function 0x%x\n", funcmode); + return -EOPNOTSUPP; + } + return 0; +@@ -10493,8 +10494,8 @@ static void dytc_profile_refresh(void) + return; + + perfmode = (output >> DYTC_GET_MODE_BIT) & 0xF; +- convert_dytc_to_profile(funcmode, perfmode, &profile); +- if (profile != dytc_current_profile) { ++ err = convert_dytc_to_profile(funcmode, perfmode, &profile); ++ if (!err && profile != dytc_current_profile) { + dytc_current_profile = profile; + platform_profile_notify(); + } +diff --git a/drivers/platform/x86/touchscreen_dmi.c b/drivers/platform/x86/touchscreen_dmi.c +index 0c67337726984..969477c83e56e 100644 +--- a/drivers/platform/x86/touchscreen_dmi.c ++++ b/drivers/platform/x86/touchscreen_dmi.c +@@ -81,7 +81,7 @@ static const struct property_entry chuwi_hi8_air_props[] = { + }; + + static const struct ts_dmi_data chuwi_hi8_air_data = { +- .acpi_name = "MSSL1680:00", ++ .acpi_name = "MSSL1680", + .properties = chuwi_hi8_air_props, + }; + +@@ -944,6 +944,32 @@ static const struct ts_dmi_data teclast_tbook11_data = { + .properties = teclast_tbook11_props, + }; + ++static const struct property_entry teclast_x16_plus_props[] = { ++ PROPERTY_ENTRY_U32("touchscreen-min-x", 8), ++ PROPERTY_ENTRY_U32("touchscreen-min-y", 14), ++ PROPERTY_ENTRY_U32("touchscreen-size-x", 1916), ++ PROPERTY_ENTRY_U32("touchscreen-size-y", 1264), ++ PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"), ++ PROPERTY_ENTRY_STRING("firmware-name", "gsl3692-teclast-x16-plus.fw"), ++ PROPERTY_ENTRY_U32("silead,max-fingers", 10), ++ PROPERTY_ENTRY_BOOL("silead,home-button"), ++ { } ++}; ++ ++static const struct ts_dmi_data teclast_x16_plus_data = { ++ .embedded_fw = { ++ .name = "silead/gsl3692-teclast-x16-plus.fw", ++ .prefix = { 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 }, ++ .length = 43560, ++ .sha256 = { 0x9d, 0xb0, 0x3d, 0xf1, 0x00, 0x3c, 0xb5, 0x25, ++ 0x62, 0x8a, 0xa0, 0x93, 0x4b, 0xe0, 0x4e, 0x75, ++ 0xd1, 0x27, 0xb1, 0x65, 0x3c, 0xba, 0xa5, 0x0f, ++ 0xcd, 0xb4, 0xbe, 0x00, 0xbb, 0xf6, 0x43, 0x29 }, ++ }, ++ .acpi_name = "MSSL1680:00", ++ .properties = teclast_x16_plus_props, ++}; ++ + static const struct property_entry teclast_x3_plus_props[] = { + PROPERTY_ENTRY_U32("touchscreen-size-x", 1980), + PROPERTY_ENTRY_U32("touchscreen-size-y", 1500), +@@ -1612,6 +1638,15 @@ const struct dmi_system_id touchscreen_dmi_table[] = { + DMI_MATCH(DMI_PRODUCT_SKU, "E5A6_A1"), + }, + }, ++ { ++ /* Teclast X16 Plus */ ++ .driver_data = (void *)&teclast_x16_plus_data, ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "TECLAST"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Default string"), ++ DMI_MATCH(DMI_PRODUCT_SKU, "D3A5_A1"), ++ }, ++ }, + { + /* Teclast X3 Plus */ + .driver_data = (void *)&teclast_x3_plus_data, +@@ -1786,7 +1821,7 @@ static void ts_dmi_add_props(struct i2c_client *client) + int error; + + if (has_acpi_companion(dev) && +- !strncmp(ts_data->acpi_name, client->name, I2C_NAME_SIZE)) { ++ strstarts(client->name, ts_data->acpi_name)) { + error = device_create_managed_software_node(dev, ts_data->properties, NULL); + if (error) + dev_err(dev, "failed to add properties: %d\n", error); +diff --git a/drivers/platform/x86/x86-android-tablets/core.c b/drivers/platform/x86/x86-android-tablets/core.c +index b55957bde0342..ac2e8caaa8526 100644 +--- a/drivers/platform/x86/x86-android-tablets/core.c ++++ b/drivers/platform/x86/x86-android-tablets/core.c +@@ -113,6 +113,9 @@ int x86_acpi_irq_helper_get(const struct x86_acpi_irq_data *data) + if (irq_type != IRQ_TYPE_NONE && irq_type != irq_get_trigger_type(irq)) + irq_set_irq_type(irq, irq_type); + ++ if (data->free_gpio) ++ devm_gpiod_put(&x86_android_tablet_device->dev, gpiod); ++ + return irq; + case X86_ACPI_IRQ_TYPE_PMIC: + status = acpi_get_handle(NULL, data->chip, &handle); +diff --git a/drivers/platform/x86/x86-android-tablets/lenovo.c b/drivers/platform/x86/x86-android-tablets/lenovo.c +index c1e68211283fb..50ac5afa0027e 100644 +--- a/drivers/platform/x86/x86-android-tablets/lenovo.c ++++ b/drivers/platform/x86/x86-android-tablets/lenovo.c +@@ -96,6 +96,7 @@ static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst + .trigger = ACPI_EDGE_SENSITIVE, + .polarity = ACPI_ACTIVE_LOW, + .con_id = "goodix_ts_irq", ++ .free_gpio = true, + }, + }, { + /* Wacom Digitizer in keyboard half */ +diff --git a/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h b/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h +index 9d2fb7fded6d7..136a2b359dd22 100644 +--- a/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h ++++ b/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h +@@ -38,6 +38,7 @@ struct x86_acpi_irq_data { + int index; + int trigger; /* ACPI_EDGE_SENSITIVE / ACPI_LEVEL_SENSITIVE */ + int polarity; /* ACPI_ACTIVE_HIGH / ACPI_ACTIVE_LOW / ACPI_ACTIVE_BOTH */ ++ bool free_gpio; /* Release GPIO after getting IRQ (for TYPE_GPIOINT) */ + const char *con_id; + }; + +diff --git a/drivers/regulator/max5970-regulator.c b/drivers/regulator/max5970-regulator.c +index bc88a40a88d4c..830a1c4cd7057 100644 +--- a/drivers/regulator/max5970-regulator.c ++++ b/drivers/regulator/max5970-regulator.c +@@ -392,7 +392,7 @@ static int max597x_regmap_read_clear(struct regmap *map, unsigned int reg, + return ret; + + if (*val) +- return regmap_write(map, reg, *val); ++ return regmap_write(map, reg, 0); + + return 0; + } +diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c +index 2aff6db748e2c..e33d10df7a763 100644 +--- a/drivers/regulator/pwm-regulator.c ++++ b/drivers/regulator/pwm-regulator.c +@@ -158,6 +158,9 @@ static int pwm_regulator_get_voltage(struct regulator_dev *rdev) + pwm_get_state(drvdata->pwm, &pstate); + + voltage = pwm_get_relative_duty_cycle(&pstate, duty_unit); ++ if (voltage < min(max_uV_duty, min_uV_duty) || ++ voltage > max(max_uV_duty, min_uV_duty)) ++ return -ENOTRECOVERABLE; + + /* + * The dutycycle for min_uV might be greater than the one for max_uV. +diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c +index c533d1dadc6bb..a5dba3829769c 100644 +--- a/drivers/s390/cio/device_ops.c ++++ b/drivers/s390/cio/device_ops.c +@@ -202,7 +202,8 @@ int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa, + return -EINVAL; + if (cdev->private->state == DEV_STATE_NOT_OPER) + return -ENODEV; +- if (cdev->private->state == DEV_STATE_VERIFY) { ++ if (cdev->private->state == DEV_STATE_VERIFY || ++ cdev->private->flags.doverify) { + /* Remember to fake irb when finished. */ + if (!cdev->private->flags.fake_irb) { + cdev->private->flags.fake_irb = FAKE_CMD_IRB; +@@ -214,8 +215,7 @@ int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa, + } + if (cdev->private->state != DEV_STATE_ONLINE || + ((sch->schib.scsw.cmd.stctl & SCSW_STCTL_PRIM_STATUS) && +- !(sch->schib.scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS)) || +- cdev->private->flags.doverify) ++ !(sch->schib.scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS))) + return -EBUSY; + ret = cio_set_options (sch, flags); + if (ret) +diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig +index addac7fbe37b9..9ce27092729c3 100644 +--- a/drivers/scsi/Kconfig ++++ b/drivers/scsi/Kconfig +@@ -1270,7 +1270,7 @@ source "drivers/scsi/arm/Kconfig" + + config JAZZ_ESP + bool "MIPS JAZZ FAS216 SCSI support" +- depends on MACH_JAZZ && SCSI ++ depends on MACH_JAZZ && SCSI=y + select SCSI_SPI_ATTRS + help + This is the driver for the onboard SCSI host adapter of MIPS Magnum +diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c +index d26941b131fdb..bf879d81846b6 100644 +--- a/drivers/scsi/lpfc/lpfc_scsi.c ++++ b/drivers/scsi/lpfc/lpfc_scsi.c +@@ -1918,7 +1918,7 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, + * + * Returns the number of SGEs added to the SGL. + **/ +-static int ++static uint32_t + lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc, + struct sli4_sge *sgl, int datasegcnt, + struct lpfc_io_buf *lpfc_cmd) +@@ -1926,8 +1926,8 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc, + struct scatterlist *sgde = NULL; /* s/g data entry */ + struct sli4_sge_diseed *diseed = NULL; + dma_addr_t physaddr; +- int i = 0, num_sge = 0, status; +- uint32_t reftag; ++ int i = 0, status; ++ uint32_t reftag, num_sge = 0; + uint8_t txop, rxop; + #ifdef CONFIG_SCSI_LPFC_DEBUG_FS + uint32_t rc; +@@ -2099,7 +2099,7 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc, + * + * Returns the number of SGEs added to the SGL. + **/ +-static int ++static uint32_t + lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, + struct sli4_sge *sgl, int datacnt, int protcnt, + struct lpfc_io_buf *lpfc_cmd) +@@ -2123,8 +2123,8 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, + uint32_t rc; + #endif + uint32_t checking = 1; +- uint32_t dma_offset = 0; +- int num_sge = 0, j = 2; ++ uint32_t dma_offset = 0, num_sge = 0; ++ int j = 2; + struct sli4_hybrid_sgl *sgl_xtra = NULL; + + sgpe = scsi_prot_sglist(sc); +diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c +index 76d369343c7a9..8cad9792a5627 100644 +--- a/drivers/scsi/scsi.c ++++ b/drivers/scsi/scsi.c +@@ -328,21 +328,39 @@ static int scsi_vpd_inquiry(struct scsi_device *sdev, unsigned char *buffer, + return result + 4; + } + ++enum scsi_vpd_parameters { ++ SCSI_VPD_HEADER_SIZE = 4, ++ SCSI_VPD_LIST_SIZE = 36, ++}; ++ + static int scsi_get_vpd_size(struct scsi_device *sdev, u8 page) + { +- unsigned char vpd_header[SCSI_VPD_HEADER_SIZE] __aligned(4); ++ unsigned char vpd[SCSI_VPD_LIST_SIZE] __aligned(4); + int result; + + if (sdev->no_vpd_size) + return SCSI_DEFAULT_VPD_LEN; + ++ /* ++ * Fetch the supported pages VPD and validate that the requested page ++ * number is present. ++ */ ++ if (page != 0) { ++ result = scsi_vpd_inquiry(sdev, vpd, 0, sizeof(vpd)); ++ if (result < SCSI_VPD_HEADER_SIZE) ++ return 0; ++ ++ result -= SCSI_VPD_HEADER_SIZE; ++ if (!memchr(&vpd[SCSI_VPD_HEADER_SIZE], page, result)) ++ return 0; ++ } + /* + * Fetch the VPD page header to find out how big the page + * is. This is done to prevent problems on legacy devices + * which can not handle allocation lengths as large as + * potentially requested by the caller. + */ +- result = scsi_vpd_inquiry(sdev, vpd_header, page, sizeof(vpd_header)); ++ result = scsi_vpd_inquiry(sdev, vpd, page, SCSI_VPD_HEADER_SIZE); + if (result < 0) + return 0; + +diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c +index 542a4bbb21bce..a12ff43ac8fd0 100644 +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -3410,6 +3410,24 @@ static bool sd_validate_opt_xfer_size(struct scsi_disk *sdkp, + return true; + } + ++static void sd_read_block_zero(struct scsi_disk *sdkp) ++{ ++ unsigned int buf_len = sdkp->device->sector_size; ++ char *buffer, cmd[10] = { }; ++ ++ buffer = kmalloc(buf_len, GFP_KERNEL); ++ if (!buffer) ++ return; ++ ++ cmd[0] = READ_10; ++ put_unaligned_be32(0, &cmd[2]); /* Logical block address 0 */ ++ put_unaligned_be16(1, &cmd[7]); /* Transfer 1 logical block */ ++ ++ scsi_execute_cmd(sdkp->device, cmd, REQ_OP_DRV_IN, buffer, buf_len, ++ SD_TIMEOUT, sdkp->max_retries, NULL); ++ kfree(buffer); ++} ++ + /** + * sd_revalidate_disk - called the first time a new disk is seen, + * performs disk spin up, read_capacity, etc. +@@ -3449,7 +3467,13 @@ static int sd_revalidate_disk(struct gendisk *disk) + */ + if (sdkp->media_present) { + sd_read_capacity(sdkp, buffer); +- ++ /* ++ * Some USB/UAS devices return generic values for mode pages ++ * until the media has been accessed. Trigger a READ operation ++ * to force the device to populate mode pages. ++ */ ++ if (sdp->read_before_ms) ++ sd_read_block_zero(sdkp); + /* + * set the default to rotational. All non-rotational devices + * support the block characteristics VPD page, which will +diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h +index 0419401835169..cdedc271857aa 100644 +--- a/drivers/scsi/smartpqi/smartpqi.h ++++ b/drivers/scsi/smartpqi/smartpqi.h +@@ -1347,7 +1347,6 @@ struct pqi_ctrl_info { + bool controller_online; + bool block_requests; + bool scan_blocked; +- u8 logical_volume_rescan_needed : 1; + u8 inbound_spanning_supported : 1; + u8 outbound_spanning_supported : 1; + u8 pqi_mode_enabled : 1; +diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c +index 9a58df9312fa7..868453b18c9ae 100644 +--- a/drivers/scsi/smartpqi/smartpqi_init.c ++++ b/drivers/scsi/smartpqi/smartpqi_init.c +@@ -2093,8 +2093,6 @@ static void pqi_scsi_update_device(struct pqi_ctrl_info *ctrl_info, + if (existing_device->devtype == TYPE_DISK) { + existing_device->raid_level = new_device->raid_level; + existing_device->volume_status = new_device->volume_status; +- if (ctrl_info->logical_volume_rescan_needed) +- existing_device->rescan = true; + memset(existing_device->next_bypass_group, 0, sizeof(existing_device->next_bypass_group)); + if (!pqi_raid_maps_equal(existing_device->raid_map, new_device->raid_map)) { + kfree(existing_device->raid_map); +@@ -2164,6 +2162,20 @@ static inline void pqi_init_device_tmf_work(struct pqi_scsi_dev *device) + INIT_WORK(&tmf_work->work_struct, pqi_tmf_worker); + } + ++static inline bool pqi_volume_rescan_needed(struct pqi_scsi_dev *device) ++{ ++ if (pqi_device_in_remove(device)) ++ return false; ++ ++ if (device->sdev == NULL) ++ return false; ++ ++ if (!scsi_device_online(device->sdev)) ++ return false; ++ ++ return device->rescan; ++} ++ + static void pqi_update_device_list(struct pqi_ctrl_info *ctrl_info, + struct pqi_scsi_dev *new_device_list[], unsigned int num_new_devices) + { +@@ -2284,9 +2296,13 @@ static void pqi_update_device_list(struct pqi_ctrl_info *ctrl_info, + if (device->sdev && device->queue_depth != device->advertised_queue_depth) { + device->advertised_queue_depth = device->queue_depth; + scsi_change_queue_depth(device->sdev, device->advertised_queue_depth); +- if (device->rescan) { +- scsi_rescan_device(device->sdev); ++ spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags); ++ if (pqi_volume_rescan_needed(device)) { + device->rescan = false; ++ spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); ++ scsi_rescan_device(device->sdev); ++ } else { ++ spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); + } + } + } +@@ -2308,8 +2324,6 @@ static void pqi_update_device_list(struct pqi_ctrl_info *ctrl_info, + } + } + +- ctrl_info->logical_volume_rescan_needed = false; +- + } + + static inline bool pqi_is_supported_device(struct pqi_scsi_dev *device) +@@ -3702,6 +3716,21 @@ static bool pqi_ofa_process_event(struct pqi_ctrl_info *ctrl_info, + return ack_event; + } + ++static void pqi_mark_volumes_for_rescan(struct pqi_ctrl_info *ctrl_info) ++{ ++ unsigned long flags; ++ struct pqi_scsi_dev *device; ++ ++ spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags); ++ ++ list_for_each_entry(device, &ctrl_info->scsi_device_list, scsi_device_list_entry) { ++ if (pqi_is_logical_device(device) && device->devtype == TYPE_DISK) ++ device->rescan = true; ++ } ++ ++ spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); ++} ++ + static void pqi_disable_raid_bypass(struct pqi_ctrl_info *ctrl_info) + { + unsigned long flags; +@@ -3742,7 +3771,7 @@ static void pqi_event_worker(struct work_struct *work) + ack_event = true; + rescan_needed = true; + if (event->event_type == PQI_EVENT_TYPE_LOGICAL_DEVICE) +- ctrl_info->logical_volume_rescan_needed = true; ++ pqi_mark_volumes_for_rescan(ctrl_info); + else if (event->event_type == PQI_EVENT_TYPE_AIO_STATE_CHANGE) + pqi_disable_raid_bypass(ctrl_info); + } +@@ -6504,8 +6533,11 @@ static void pqi_map_queues(struct Scsi_Host *shost) + { + struct pqi_ctrl_info *ctrl_info = shost_to_hba(shost); + +- blk_mq_pci_map_queues(&shost->tag_set.map[HCTX_TYPE_DEFAULT], ++ if (!ctrl_info->disable_managed_interrupts) ++ return blk_mq_pci_map_queues(&shost->tag_set.map[HCTX_TYPE_DEFAULT], + ctrl_info->pci_dev, 0); ++ else ++ return blk_mq_map_queues(&shost->tag_set.map[HCTX_TYPE_DEFAULT]); + } + + static inline bool pqi_is_tape_changer_device(struct pqi_scsi_dev *device) +@@ -10142,6 +10174,18 @@ static const struct pci_device_id pqi_pci_id_table[] = { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1014, 0x0718) + }, ++ { ++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, ++ 0x1137, 0x02f8) ++ }, ++ { ++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, ++ 0x1137, 0x02f9) ++ }, ++ { ++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, ++ 0x1137, 0x02fa) ++ }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1e93, 0x1000) +@@ -10198,6 +10242,34 @@ static const struct pci_device_id pqi_pci_id_table[] = { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1f51, 0x100a) + }, ++ { ++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, ++ 0x1f51, 0x100e) ++ }, ++ { ++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, ++ 0x1f51, 0x100f) ++ }, ++ { ++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, ++ 0x1f51, 0x1010) ++ }, ++ { ++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, ++ 0x1f51, 0x1011) ++ }, ++ { ++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, ++ 0x1f51, 0x1043) ++ }, ++ { ++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, ++ 0x1f51, 0x1044) ++ }, ++ { ++ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, ++ 0x1f51, 0x1045) ++ }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + PCI_ANY_ID, PCI_ANY_ID) +diff --git a/drivers/spi/spi-cs42l43.c b/drivers/spi/spi-cs42l43.c +index d239fc5a49ccc..c1556b6529092 100644 +--- a/drivers/spi/spi-cs42l43.c ++++ b/drivers/spi/spi-cs42l43.c +@@ -244,7 +244,10 @@ static int cs42l43_spi_probe(struct platform_device *pdev) + priv->ctlr->use_gpio_descriptors = true; + priv->ctlr->auto_runtime_pm = true; + +- devm_pm_runtime_enable(priv->dev); ++ ret = devm_pm_runtime_enable(priv->dev); ++ if (ret) ++ return ret; ++ + pm_runtime_idle(priv->dev); + + regmap_write(priv->regmap, CS42L43_TRAN_CONFIG6, CS42L43_FIFO_SIZE - 1); +diff --git a/drivers/spi/spi-hisi-sfc-v3xx.c b/drivers/spi/spi-hisi-sfc-v3xx.c +index 9d22018f7985f..1301d14483d48 100644 +--- a/drivers/spi/spi-hisi-sfc-v3xx.c ++++ b/drivers/spi/spi-hisi-sfc-v3xx.c +@@ -377,6 +377,11 @@ static const struct spi_controller_mem_ops hisi_sfc_v3xx_mem_ops = { + static irqreturn_t hisi_sfc_v3xx_isr(int irq, void *data) + { + struct hisi_sfc_v3xx_host *host = data; ++ u32 reg; ++ ++ reg = readl(host->regbase + HISI_SFC_V3XX_INT_STAT); ++ if (!reg) ++ return IRQ_NONE; + + hisi_sfc_v3xx_disable_int(host); + +diff --git a/drivers/spi/spi-intel-pci.c b/drivers/spi/spi-intel-pci.c +index b9918dcc38027..07d20ca1164c3 100644 +--- a/drivers/spi/spi-intel-pci.c ++++ b/drivers/spi/spi-intel-pci.c +@@ -76,6 +76,7 @@ static const struct pci_device_id intel_spi_pci_ids[] = { + { PCI_VDEVICE(INTEL, 0x7a24), (unsigned long)&cnl_info }, + { PCI_VDEVICE(INTEL, 0x7aa4), (unsigned long)&cnl_info }, + { PCI_VDEVICE(INTEL, 0x7e23), (unsigned long)&cnl_info }, ++ { PCI_VDEVICE(INTEL, 0x7f24), (unsigned long)&cnl_info }, + { PCI_VDEVICE(INTEL, 0x9d24), (unsigned long)&cnl_info }, + { PCI_VDEVICE(INTEL, 0x9da4), (unsigned long)&cnl_info }, + { PCI_VDEVICE(INTEL, 0xa0a4), (unsigned long)&cnl_info }, +diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c +index cfc3b1ddbd229..6f12e4fb2e2e1 100644 +--- a/drivers/spi/spi-sh-msiof.c ++++ b/drivers/spi/spi-sh-msiof.c +@@ -136,14 +136,14 @@ struct sh_msiof_spi_priv { + + /* SIFCTR */ + #define SIFCTR_TFWM_MASK GENMASK(31, 29) /* Transmit FIFO Watermark */ +-#define SIFCTR_TFWM_64 (0 << 29) /* Transfer Request when 64 empty stages */ +-#define SIFCTR_TFWM_32 (1 << 29) /* Transfer Request when 32 empty stages */ +-#define SIFCTR_TFWM_24 (2 << 29) /* Transfer Request when 24 empty stages */ +-#define SIFCTR_TFWM_16 (3 << 29) /* Transfer Request when 16 empty stages */ +-#define SIFCTR_TFWM_12 (4 << 29) /* Transfer Request when 12 empty stages */ +-#define SIFCTR_TFWM_8 (5 << 29) /* Transfer Request when 8 empty stages */ +-#define SIFCTR_TFWM_4 (6 << 29) /* Transfer Request when 4 empty stages */ +-#define SIFCTR_TFWM_1 (7 << 29) /* Transfer Request when 1 empty stage */ ++#define SIFCTR_TFWM_64 (0UL << 29) /* Transfer Request when 64 empty stages */ ++#define SIFCTR_TFWM_32 (1UL << 29) /* Transfer Request when 32 empty stages */ ++#define SIFCTR_TFWM_24 (2UL << 29) /* Transfer Request when 24 empty stages */ ++#define SIFCTR_TFWM_16 (3UL << 29) /* Transfer Request when 16 empty stages */ ++#define SIFCTR_TFWM_12 (4UL << 29) /* Transfer Request when 12 empty stages */ ++#define SIFCTR_TFWM_8 (5UL << 29) /* Transfer Request when 8 empty stages */ ++#define SIFCTR_TFWM_4 (6UL << 29) /* Transfer Request when 4 empty stages */ ++#define SIFCTR_TFWM_1 (7UL << 29) /* Transfer Request when 1 empty stage */ + #define SIFCTR_TFUA_MASK GENMASK(26, 20) /* Transmit FIFO Usable Area */ + #define SIFCTR_TFUA_SHIFT 20 + #define SIFCTR_TFUA(i) ((i) << SIFCTR_TFUA_SHIFT) +diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c +index 506193e870c49..7a85e6477e465 100644 +--- a/drivers/target/target_core_device.c ++++ b/drivers/target/target_core_device.c +@@ -147,7 +147,6 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd) + struct se_session *se_sess = se_cmd->se_sess; + struct se_node_acl *nacl = se_sess->se_node_acl; + struct se_tmr_req *se_tmr = se_cmd->se_tmr_req; +- unsigned long flags; + + rcu_read_lock(); + deve = target_nacl_find_deve(nacl, se_cmd->orig_fe_lun); +@@ -178,10 +177,6 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd) + se_cmd->se_dev = rcu_dereference_raw(se_lun->lun_se_dev); + se_tmr->tmr_dev = rcu_dereference_raw(se_lun->lun_se_dev); + +- spin_lock_irqsave(&se_tmr->tmr_dev->se_tmr_lock, flags); +- list_add_tail(&se_tmr->tmr_list, &se_tmr->tmr_dev->dev_tmr_list); +- spin_unlock_irqrestore(&se_tmr->tmr_dev->se_tmr_lock, flags); +- + return 0; + } + EXPORT_SYMBOL(transport_lookup_tmr_lun); +diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c +index 41b7489d37ce9..ed4fd22eac6e0 100644 +--- a/drivers/target/target_core_pscsi.c ++++ b/drivers/target/target_core_pscsi.c +@@ -907,12 +907,15 @@ pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, + + return 0; + fail: +- if (bio) +- bio_put(bio); ++ if (bio) { ++ bio_uninit(bio); ++ kfree(bio); ++ } + while (req->bio) { + bio = req->bio; + req->bio = bio->bi_next; +- bio_put(bio); ++ bio_uninit(bio); ++ kfree(bio); + } + req->biotail = NULL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; +diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c +index 670cfb7bd426a..73d0d6133ac8f 100644 +--- a/drivers/target/target_core_transport.c ++++ b/drivers/target/target_core_transport.c +@@ -3629,6 +3629,10 @@ int transport_generic_handle_tmr( + unsigned long flags; + bool aborted = false; + ++ spin_lock_irqsave(&cmd->se_dev->se_tmr_lock, flags); ++ list_add_tail(&cmd->se_tmr_req->tmr_list, &cmd->se_dev->dev_tmr_list); ++ spin_unlock_irqrestore(&cmd->se_dev->se_tmr_lock, flags); ++ + spin_lock_irqsave(&cmd->t_state_lock, flags); + if (cmd->transport_state & CMD_T_ABORTED) { + aborted = true; +diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c +index b7635363373e2..474e2b7f43fe1 100644 +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -1345,11 +1345,41 @@ static void pl011_start_tx_pio(struct uart_amba_port *uap) + } + } + ++static void pl011_rs485_tx_start(struct uart_amba_port *uap) ++{ ++ struct uart_port *port = &uap->port; ++ u32 cr; ++ ++ /* Enable transmitter */ ++ cr = pl011_read(uap, REG_CR); ++ cr |= UART011_CR_TXE; ++ ++ /* Disable receiver if half-duplex */ ++ if (!(port->rs485.flags & SER_RS485_RX_DURING_TX)) ++ cr &= ~UART011_CR_RXE; ++ ++ if (port->rs485.flags & SER_RS485_RTS_ON_SEND) ++ cr &= ~UART011_CR_RTS; ++ else ++ cr |= UART011_CR_RTS; ++ ++ pl011_write(cr, uap, REG_CR); ++ ++ if (port->rs485.delay_rts_before_send) ++ mdelay(port->rs485.delay_rts_before_send); ++ ++ uap->rs485_tx_started = true; ++} ++ + static void pl011_start_tx(struct uart_port *port) + { + struct uart_amba_port *uap = + container_of(port, struct uart_amba_port, port); + ++ if ((uap->port.rs485.flags & SER_RS485_ENABLED) && ++ !uap->rs485_tx_started) ++ pl011_rs485_tx_start(uap); ++ + if (!pl011_dma_tx_start(uap)) + pl011_start_tx_pio(uap); + } +@@ -1431,42 +1461,12 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c, + return true; + } + +-static void pl011_rs485_tx_start(struct uart_amba_port *uap) +-{ +- struct uart_port *port = &uap->port; +- u32 cr; +- +- /* Enable transmitter */ +- cr = pl011_read(uap, REG_CR); +- cr |= UART011_CR_TXE; +- +- /* Disable receiver if half-duplex */ +- if (!(port->rs485.flags & SER_RS485_RX_DURING_TX)) +- cr &= ~UART011_CR_RXE; +- +- if (port->rs485.flags & SER_RS485_RTS_ON_SEND) +- cr &= ~UART011_CR_RTS; +- else +- cr |= UART011_CR_RTS; +- +- pl011_write(cr, uap, REG_CR); +- +- if (port->rs485.delay_rts_before_send) +- mdelay(port->rs485.delay_rts_before_send); +- +- uap->rs485_tx_started = true; +-} +- + /* Returns true if tx interrupts have to be (kept) enabled */ + static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq) + { + struct circ_buf *xmit = &uap->port.state->xmit; + int count = uap->fifosize >> 1; + +- if ((uap->port.rs485.flags & SER_RS485_ENABLED) && +- !uap->rs485_tx_started) +- pl011_rs485_tx_start(uap); +- + if (uap->port.x_char) { + if (!pl011_tx_char(uap, uap->port.x_char, from_irq)) + return true; +diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c +index fc7fd40bca988..e93e3a9b48838 100644 +--- a/drivers/tty/serial/stm32-usart.c ++++ b/drivers/tty/serial/stm32-usart.c +@@ -251,7 +251,9 @@ static int stm32_usart_config_rs485(struct uart_port *port, struct ktermios *ter + writel_relaxed(cr3, port->membase + ofs->cr3); + writel_relaxed(cr1, port->membase + ofs->cr1); + +- rs485conf->flags |= SER_RS485_RX_DURING_TX; ++ if (!port->rs485_rx_during_tx_gpio) ++ rs485conf->flags |= SER_RS485_RX_DURING_TX; ++ + } else { + stm32_usart_clr_bits(port, ofs->cr3, + USART_CR3_DEM | USART_CR3_DEP); +diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c +index 1f8d86b9c4fa0..d2d760143ca30 100644 +--- a/drivers/ufs/core/ufshcd.c ++++ b/drivers/ufs/core/ufshcd.c +@@ -1456,7 +1456,7 @@ static int ufshcd_devfreq_target(struct device *dev, + int ret = 0; + struct ufs_hba *hba = dev_get_drvdata(dev); + ktime_t start; +- bool scale_up, sched_clk_scaling_suspend_work = false; ++ bool scale_up = false, sched_clk_scaling_suspend_work = false; + struct list_head *clk_list = &hba->clk_list_head; + struct ufs_clk_info *clki; + unsigned long irq_flags; +@@ -3045,7 +3045,7 @@ bool ufshcd_cmd_inflight(struct scsi_cmnd *cmd) + */ + static int ufshcd_clear_cmd(struct ufs_hba *hba, u32 task_tag) + { +- u32 mask = 1U << task_tag; ++ u32 mask; + unsigned long flags; + int err; + +@@ -3063,6 +3063,8 @@ static int ufshcd_clear_cmd(struct ufs_hba *hba, u32 task_tag) + return 0; + } + ++ mask = 1U << task_tag; ++ + /* clear outstanding transaction before retry */ + spin_lock_irqsave(hba->host->host_lock, flags); + ufshcd_utrl_clear(hba, mask); +@@ -6348,7 +6350,6 @@ static void ufshcd_err_handling_prepare(struct ufs_hba *hba) + ufshcd_hold(hba); + if (!ufshcd_is_clkgating_allowed(hba)) + ufshcd_setup_clocks(hba, true); +- ufshcd_release(hba); + pm_op = hba->is_sys_suspended ? UFS_SYSTEM_PM : UFS_RUNTIME_PM; + ufshcd_vops_resume(hba, pm_op); + } else { +diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c +index d140010257004..b1b46c7c63f8b 100644 +--- a/drivers/usb/cdns3/cdns3-gadget.c ++++ b/drivers/usb/cdns3/cdns3-gadget.c +@@ -828,7 +828,11 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep, + return; + } + +- if (request->complete) { ++ /* ++ * zlp request is appended by driver, needn't call usb_gadget_giveback_request() to notify ++ * gadget composite driver. ++ */ ++ if (request->complete && request->buf != priv_dev->zlp_buf) { + spin_unlock(&priv_dev->lock); + usb_gadget_giveback_request(&priv_ep->endpoint, + request); +@@ -2539,11 +2543,11 @@ static int cdns3_gadget_ep_disable(struct usb_ep *ep) + + while (!list_empty(&priv_ep->wa2_descmiss_req_list)) { + priv_req = cdns3_next_priv_request(&priv_ep->wa2_descmiss_req_list); ++ list_del_init(&priv_req->list); + + kfree(priv_req->request.buf); + cdns3_gadget_ep_free_request(&priv_ep->endpoint, + &priv_req->request); +- list_del_init(&priv_req->list); + --priv_ep->wa2_counter; + } + +diff --git a/drivers/usb/cdns3/core.c b/drivers/usb/cdns3/core.c +index 33548771a0d3a..465e9267b49c1 100644 +--- a/drivers/usb/cdns3/core.c ++++ b/drivers/usb/cdns3/core.c +@@ -395,7 +395,6 @@ static int cdns_role_set(struct usb_role_switch *sw, enum usb_role role) + return ret; + } + +- + /** + * cdns_wakeup_irq - interrupt handler for wakeup events + * @irq: irq number for cdns3/cdnsp core device +diff --git a/drivers/usb/cdns3/drd.c b/drivers/usb/cdns3/drd.c +index 04b6d12f2b9a3..ee917f1b091c8 100644 +--- a/drivers/usb/cdns3/drd.c ++++ b/drivers/usb/cdns3/drd.c +@@ -156,7 +156,8 @@ bool cdns_is_device(struct cdns *cdns) + */ + static void cdns_otg_disable_irq(struct cdns *cdns) + { +- writel(0, &cdns->otg_irq_regs->ien); ++ if (cdns->version) ++ writel(0, &cdns->otg_irq_regs->ien); + } + + /** +@@ -422,15 +423,20 @@ int cdns_drd_init(struct cdns *cdns) + + cdns->otg_regs = (void __iomem *)&cdns->otg_v1_regs->cmd; + +- if (readl(&cdns->otg_cdnsp_regs->did) == OTG_CDNSP_DID) { ++ state = readl(&cdns->otg_cdnsp_regs->did); ++ ++ if (OTG_CDNSP_CHECK_DID(state)) { + cdns->otg_irq_regs = (struct cdns_otg_irq_regs __iomem *) + &cdns->otg_cdnsp_regs->ien; + cdns->version = CDNSP_CONTROLLER_V2; +- } else { ++ } else if (OTG_CDNS3_CHECK_DID(state)) { + cdns->otg_irq_regs = (struct cdns_otg_irq_regs __iomem *) + &cdns->otg_v1_regs->ien; + writel(1, &cdns->otg_v1_regs->simulate); + cdns->version = CDNS3_CONTROLLER_V1; ++ } else { ++ dev_err(cdns->dev, "not supporte DID=0x%08x\n", state); ++ return -EINVAL; + } + + dev_dbg(cdns->dev, "DRD version v1 (ID: %08x, rev: %08x)\n", +@@ -483,7 +489,6 @@ int cdns_drd_exit(struct cdns *cdns) + return 0; + } + +- + /* Indicate the cdns3 core was power lost before */ + bool cdns_power_is_lost(struct cdns *cdns) + { +diff --git a/drivers/usb/cdns3/drd.h b/drivers/usb/cdns3/drd.h +index cbdf94f73ed91..d72370c321d39 100644 +--- a/drivers/usb/cdns3/drd.h ++++ b/drivers/usb/cdns3/drd.h +@@ -79,7 +79,11 @@ struct cdnsp_otg_regs { + __le32 susp_timing_ctrl; + }; + +-#define OTG_CDNSP_DID 0x0004034E ++/* CDNSP driver supports 0x000403xx Cadence USB controller family. */ ++#define OTG_CDNSP_CHECK_DID(did) (((did) & GENMASK(31, 8)) == 0x00040300) ++ ++/* CDNS3 driver supports 0x000402xx Cadence USB controller family. */ ++#define OTG_CDNS3_CHECK_DID(did) (((did) & GENMASK(31, 8)) == 0x00040200) + + /* + * Common registers interface for both CDNS3 and CDNSP version of DRD. +diff --git a/drivers/usb/cdns3/host.c b/drivers/usb/cdns3/host.c +index 6164fc4c96a49..ceca4d839dfd4 100644 +--- a/drivers/usb/cdns3/host.c ++++ b/drivers/usb/cdns3/host.c +@@ -18,6 +18,11 @@ + #include "../host/xhci.h" + #include "../host/xhci-plat.h" + ++/* ++ * The XECP_PORT_CAP_REG and XECP_AUX_CTRL_REG1 exist only ++ * in Cadence USB3 dual-role controller, so it can't be used ++ * with Cadence CDNSP dual-role controller. ++ */ + #define XECP_PORT_CAP_REG 0x8000 + #define XECP_AUX_CTRL_REG1 0x8120 + +@@ -57,6 +62,8 @@ static const struct xhci_plat_priv xhci_plat_cdns3_xhci = { + .resume_quirk = xhci_cdns3_resume_quirk, + }; + ++static const struct xhci_plat_priv xhci_plat_cdnsp_xhci; ++ + static int __cdns_host_init(struct cdns *cdns) + { + struct platform_device *xhci; +@@ -81,8 +88,13 @@ static int __cdns_host_init(struct cdns *cdns) + goto err1; + } + +- cdns->xhci_plat_data = kmemdup(&xhci_plat_cdns3_xhci, +- sizeof(struct xhci_plat_priv), GFP_KERNEL); ++ if (cdns->version < CDNSP_CONTROLLER_V2) ++ cdns->xhci_plat_data = kmemdup(&xhci_plat_cdns3_xhci, ++ sizeof(struct xhci_plat_priv), GFP_KERNEL); ++ else ++ cdns->xhci_plat_data = kmemdup(&xhci_plat_cdnsp_xhci, ++ sizeof(struct xhci_plat_priv), GFP_KERNEL); ++ + if (!cdns->xhci_plat_data) { + ret = -ENOMEM; + goto err1; +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index 4c8dd67246788..28f49400f3e8b 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -2650,6 +2650,11 @@ static int dwc3_gadget_soft_disconnect(struct dwc3 *dwc) + int ret; + + spin_lock_irqsave(&dwc->lock, flags); ++ if (!dwc->pullups_connected) { ++ spin_unlock_irqrestore(&dwc->lock, flags); ++ return 0; ++ } ++ + dwc->connected = false; + + /* +diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c +index cc0ed29a4adc0..5712883a7527c 100644 +--- a/drivers/usb/gadget/function/f_ncm.c ++++ b/drivers/usb/gadget/function/f_ncm.c +@@ -1325,7 +1325,15 @@ static int ncm_unwrap_ntb(struct gether *port, + "Parsed NTB with %d frames\n", dgram_counter); + + to_process -= block_len; +- if (to_process != 0) { ++ ++ /* ++ * Windows NCM driver avoids USB ZLPs by adding a 1-byte ++ * zero pad as needed. ++ */ ++ if (to_process == 1 && ++ (*(unsigned char *)(ntb_ptr + block_len) == 0x00)) { ++ to_process--; ++ } else if (to_process > 0) { + ntb_ptr = (unsigned char *)(ntb_ptr + block_len); + goto parse_ntb; + } +diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c +index 10c5d7f726a1f..f90eeecf27de1 100644 +--- a/drivers/usb/gadget/udc/omap_udc.c ++++ b/drivers/usb/gadget/udc/omap_udc.c +@@ -2036,7 +2036,8 @@ static irqreturn_t omap_udc_iso_irq(int irq, void *_dev) + + static inline int machine_without_vbus_sense(void) + { +- return machine_is_omap_osk() || machine_is_sx1(); ++ return machine_is_omap_osk() || machine_is_omap_palmte() || ++ machine_is_sx1(); + } + + static int omap_udc_start(struct usb_gadget *g, +diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c +index ae41578bd0149..70165dd86b5de 100644 +--- a/drivers/usb/roles/class.c ++++ b/drivers/usb/roles/class.c +@@ -21,7 +21,9 @@ static const struct class role_class = { + struct usb_role_switch { + struct device dev; + struct mutex lock; /* device lock*/ ++ struct module *module; /* the module this device depends on */ + enum usb_role role; ++ bool registered; + + /* From descriptor */ + struct device *usb2_port; +@@ -48,6 +50,9 @@ int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role) + if (IS_ERR_OR_NULL(sw)) + return 0; + ++ if (!sw->registered) ++ return -EOPNOTSUPP; ++ + mutex_lock(&sw->lock); + + ret = sw->set(sw, role); +@@ -73,7 +78,7 @@ enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw) + { + enum usb_role role; + +- if (IS_ERR_OR_NULL(sw)) ++ if (IS_ERR_OR_NULL(sw) || !sw->registered) + return USB_ROLE_NONE; + + mutex_lock(&sw->lock); +@@ -135,7 +140,7 @@ struct usb_role_switch *usb_role_switch_get(struct device *dev) + usb_role_switch_match); + + if (!IS_ERR_OR_NULL(sw)) +- WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); ++ WARN_ON(!try_module_get(sw->module)); + + return sw; + } +@@ -157,7 +162,7 @@ struct usb_role_switch *fwnode_usb_role_switch_get(struct fwnode_handle *fwnode) + sw = fwnode_connection_find_match(fwnode, "usb-role-switch", + NULL, usb_role_switch_match); + if (!IS_ERR_OR_NULL(sw)) +- WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); ++ WARN_ON(!try_module_get(sw->module)); + + return sw; + } +@@ -172,7 +177,7 @@ EXPORT_SYMBOL_GPL(fwnode_usb_role_switch_get); + void usb_role_switch_put(struct usb_role_switch *sw) + { + if (!IS_ERR_OR_NULL(sw)) { +- module_put(sw->dev.parent->driver->owner); ++ module_put(sw->module); + put_device(&sw->dev); + } + } +@@ -189,15 +194,18 @@ struct usb_role_switch * + usb_role_switch_find_by_fwnode(const struct fwnode_handle *fwnode) + { + struct device *dev; ++ struct usb_role_switch *sw = NULL; + + if (!fwnode) + return NULL; + + dev = class_find_device_by_fwnode(&role_class, fwnode); +- if (dev) +- WARN_ON(!try_module_get(dev->parent->driver->owner)); ++ if (dev) { ++ sw = to_role_switch(dev); ++ WARN_ON(!try_module_get(sw->module)); ++ } + +- return dev ? to_role_switch(dev) : NULL; ++ return sw; + } + EXPORT_SYMBOL_GPL(usb_role_switch_find_by_fwnode); + +@@ -338,6 +346,7 @@ usb_role_switch_register(struct device *parent, + sw->set = desc->set; + sw->get = desc->get; + ++ sw->module = parent->driver->owner; + sw->dev.parent = parent; + sw->dev.fwnode = desc->fwnode; + sw->dev.class = &role_class; +@@ -352,6 +361,8 @@ usb_role_switch_register(struct device *parent, + return ERR_PTR(ret); + } + ++ sw->registered = true; ++ + /* TODO: Symlinks for the host port and the device controller. */ + + return sw; +@@ -366,8 +377,10 @@ EXPORT_SYMBOL_GPL(usb_role_switch_register); + */ + void usb_role_switch_unregister(struct usb_role_switch *sw) + { +- if (!IS_ERR_OR_NULL(sw)) ++ if (!IS_ERR_OR_NULL(sw)) { ++ sw->registered = false; + device_unregister(&sw->dev); ++ } + } + EXPORT_SYMBOL_GPL(usb_role_switch_unregister); + +diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c +index c54e9805da536..12cf9940e5b67 100644 +--- a/drivers/usb/storage/scsiglue.c ++++ b/drivers/usb/storage/scsiglue.c +@@ -179,6 +179,13 @@ static int slave_configure(struct scsi_device *sdev) + */ + sdev->use_192_bytes_for_3f = 1; + ++ /* ++ * Some devices report generic values until the media has been ++ * accessed. Force a READ(10) prior to querying device ++ * characteristics. ++ */ ++ sdev->read_before_ms = 1; ++ + /* + * Some devices don't like MODE SENSE with page=0x3f, + * which is the command used for checking if a device +diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c +index 696bb0b235992..299a6767b7b30 100644 +--- a/drivers/usb/storage/uas.c ++++ b/drivers/usb/storage/uas.c +@@ -878,6 +878,13 @@ static int uas_slave_configure(struct scsi_device *sdev) + if (devinfo->flags & US_FL_CAPACITY_HEURISTICS) + sdev->guess_capacity = 1; + ++ /* ++ * Some devices report generic values until the media has been ++ * accessed. Force a READ(10) prior to querying device ++ * characteristics. ++ */ ++ sdev->read_before_ms = 1; ++ + /* + * Some devices don't like MODE SENSE with page=0x3f, + * which is the command used for checking if a device +diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c +index bfb6f9481e87f..a8e03cfde9dda 100644 +--- a/drivers/usb/typec/tcpm/tcpm.c ++++ b/drivers/usb/typec/tcpm/tcpm.c +@@ -3730,9 +3730,6 @@ static void tcpm_detach(struct tcpm_port *port) + if (tcpm_port_is_disconnected(port)) + port->hard_reset_count = 0; + +- port->try_src_count = 0; +- port->try_snk_count = 0; +- + if (!port->attached) + return; + +diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c +index fa222080887d5..928eacbeb21ac 100644 +--- a/drivers/usb/typec/ucsi/ucsi_acpi.c ++++ b/drivers/usb/typec/ucsi/ucsi_acpi.c +@@ -25,6 +25,8 @@ struct ucsi_acpi { + unsigned long flags; + guid_t guid; + u64 cmd; ++ bool dell_quirk_probed; ++ bool dell_quirk_active; + }; + + static int ucsi_acpi_dsm(struct ucsi_acpi *ua, int func) +@@ -126,12 +128,73 @@ static const struct ucsi_operations ucsi_zenbook_ops = { + .async_write = ucsi_acpi_async_write + }; + +-static const struct dmi_system_id zenbook_dmi_id[] = { ++/* ++ * Some Dell laptops expect that an ACK command with the ++ * UCSI_ACK_CONNECTOR_CHANGE bit set is followed by a (separate) ++ * ACK command that only has the UCSI_ACK_COMMAND_COMPLETE bit set. ++ * If this is not done events are not delivered to OSPM and ++ * subsequent commands will timeout. ++ */ ++static int ++ucsi_dell_sync_write(struct ucsi *ucsi, unsigned int offset, ++ const void *val, size_t val_len) ++{ ++ struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); ++ u64 cmd = *(u64 *)val, ack = 0; ++ int ret; ++ ++ if (UCSI_COMMAND(cmd) == UCSI_ACK_CC_CI && ++ cmd & UCSI_ACK_CONNECTOR_CHANGE) ++ ack = UCSI_ACK_CC_CI | UCSI_ACK_COMMAND_COMPLETE; ++ ++ ret = ucsi_acpi_sync_write(ucsi, offset, val, val_len); ++ if (ret != 0) ++ return ret; ++ if (ack == 0) ++ return ret; ++ ++ if (!ua->dell_quirk_probed) { ++ ua->dell_quirk_probed = true; ++ ++ cmd = UCSI_GET_CAPABILITY; ++ ret = ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &cmd, ++ sizeof(cmd)); ++ if (ret == 0) ++ return ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, ++ &ack, sizeof(ack)); ++ if (ret != -ETIMEDOUT) ++ return ret; ++ ++ ua->dell_quirk_active = true; ++ dev_err(ua->dev, "Firmware bug: Additional ACK required after ACKing a connector change.\n"); ++ dev_err(ua->dev, "Firmware bug: Enabling workaround\n"); ++ } ++ ++ if (!ua->dell_quirk_active) ++ return ret; ++ ++ return ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &ack, sizeof(ack)); ++} ++ ++static const struct ucsi_operations ucsi_dell_ops = { ++ .read = ucsi_acpi_read, ++ .sync_write = ucsi_dell_sync_write, ++ .async_write = ucsi_acpi_async_write ++}; ++ ++static const struct dmi_system_id ucsi_acpi_quirks[] = { + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX325UA_UM325UA"), + }, ++ .driver_data = (void *)&ucsi_zenbook_ops, ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ++ }, ++ .driver_data = (void *)&ucsi_dell_ops, + }, + { } + }; +@@ -160,6 +223,7 @@ static int ucsi_acpi_probe(struct platform_device *pdev) + { + struct acpi_device *adev = ACPI_COMPANION(&pdev->dev); + const struct ucsi_operations *ops = &ucsi_acpi_ops; ++ const struct dmi_system_id *id; + struct ucsi_acpi *ua; + struct resource *res; + acpi_status status; +@@ -189,8 +253,9 @@ static int ucsi_acpi_probe(struct platform_device *pdev) + init_completion(&ua->complete); + ua->dev = &pdev->dev; + +- if (dmi_check_system(zenbook_dmi_id)) +- ops = &ucsi_zenbook_ops; ++ id = dmi_first_match(ucsi_acpi_quirks); ++ if (id) ++ ops = id->driver_data; + + ua->ucsi = ucsi_create(&pdev->dev, ops); + if (IS_ERR(ua->ucsi)) +diff --git a/drivers/video/fbdev/savage/savagefb_driver.c b/drivers/video/fbdev/savage/savagefb_driver.c +index dddd6afcb972a..ebc9aeffdde7c 100644 +--- a/drivers/video/fbdev/savage/savagefb_driver.c ++++ b/drivers/video/fbdev/savage/savagefb_driver.c +@@ -869,6 +869,9 @@ static int savagefb_check_var(struct fb_var_screeninfo *var, + + DBG("savagefb_check_var"); + ++ if (!var->pixclock) ++ return -EINVAL; ++ + var->transp.offset = 0; + var->transp.length = 0; + switch (var->bits_per_pixel) { +diff --git a/drivers/video/fbdev/sis/sis_main.c b/drivers/video/fbdev/sis/sis_main.c +index 6ad47b6b60046..431b1a138c111 100644 +--- a/drivers/video/fbdev/sis/sis_main.c ++++ b/drivers/video/fbdev/sis/sis_main.c +@@ -1475,6 +1475,8 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) + + vtotal = var->upper_margin + var->lower_margin + var->vsync_len; + ++ if (!var->pixclock) ++ return -EINVAL; + pixclock = var->pixclock; + + if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) { +diff --git a/fs/afs/volume.c b/fs/afs/volume.c +index 115c081a8e2ce..c028598a903c9 100644 +--- a/fs/afs/volume.c ++++ b/fs/afs/volume.c +@@ -337,7 +337,7 @@ static int afs_update_volume_status(struct afs_volume *volume, struct key *key) + { + struct afs_server_list *new, *old, *discard; + struct afs_vldb_entry *vldb; +- char idbuf[16]; ++ char idbuf[24]; + int ret, idsz; + + _enter(""); +@@ -345,7 +345,7 @@ static int afs_update_volume_status(struct afs_volume *volume, struct key *key) + /* We look up an ID by passing it as a decimal string in the + * operation's name parameter. + */ +- idsz = sprintf(idbuf, "%llu", volume->vid); ++ idsz = snprintf(idbuf, sizeof(idbuf), "%llu", volume->vid); + + vldb = afs_vl_lookup_vldb(volume->cell, key, idbuf, idsz); + if (IS_ERR(vldb)) { +diff --git a/fs/aio.c b/fs/aio.c +index f8589caef9c10..3235d4e6cc623 100644 +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -594,6 +594,13 @@ void kiocb_set_cancel_fn(struct kiocb *iocb, kiocb_cancel_fn *cancel) + struct kioctx *ctx = req->ki_ctx; + unsigned long flags; + ++ /* ++ * kiocb didn't come from aio or is neither a read nor a write, hence ++ * ignore it. ++ */ ++ if (!(iocb->ki_flags & IOCB_AIO_RW)) ++ return; ++ + if (WARN_ON_ONCE(!list_empty(&req->ki_list))) + return; + +@@ -1463,7 +1470,7 @@ static int aio_prep_rw(struct kiocb *req, const struct iocb *iocb) + req->ki_complete = aio_complete_rw; + req->private = NULL; + req->ki_pos = iocb->aio_offset; +- req->ki_flags = req->ki_filp->f_iocb_flags; ++ req->ki_flags = req->ki_filp->f_iocb_flags | IOCB_AIO_RW; + if (iocb->aio_flags & IOCB_FLAG_RESFD) + req->ki_flags |= IOCB_EVENTFD; + if (iocb->aio_flags & IOCB_FLAG_IOPRIO) { +diff --git a/fs/btrfs/defrag.c b/fs/btrfs/defrag.c +index 5244561e20168..f99c9029d91e4 100644 +--- a/fs/btrfs/defrag.c ++++ b/fs/btrfs/defrag.c +@@ -1047,7 +1047,7 @@ static int defrag_collect_targets(struct btrfs_inode *inode, + goto add; + + /* Skip too large extent */ +- if (range_len >= extent_thresh) ++ if (em->len >= extent_thresh) + goto next; + + /* +diff --git a/fs/cachefiles/cache.c b/fs/cachefiles/cache.c +index 7077f72e6f474..f449f7340aad0 100644 +--- a/fs/cachefiles/cache.c ++++ b/fs/cachefiles/cache.c +@@ -168,6 +168,8 @@ int cachefiles_add_cache(struct cachefiles_cache *cache) + dput(root); + error_open_root: + cachefiles_end_secure(cache, saved_cred); ++ put_cred(cache->cache_cred); ++ cache->cache_cred = NULL; + error_getsec: + fscache_relinquish_cache(cache_cookie); + cache->cache = NULL; +diff --git a/fs/cachefiles/daemon.c b/fs/cachefiles/daemon.c +index aa4efcabb5e37..5f4df9588620f 100644 +--- a/fs/cachefiles/daemon.c ++++ b/fs/cachefiles/daemon.c +@@ -805,6 +805,7 @@ static void cachefiles_daemon_unbind(struct cachefiles_cache *cache) + cachefiles_put_directory(cache->graveyard); + cachefiles_put_directory(cache->store); + mntput(cache->mnt); ++ put_cred(cache->cache_cred); + + kfree(cache->rootdirname); + kfree(cache->secctx); +diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c +index e8bf082105d87..ad1f46c66fbff 100644 +--- a/fs/ceph/caps.c ++++ b/fs/ceph/caps.c +@@ -3216,7 +3216,6 @@ static int ceph_try_drop_cap_snap(struct ceph_inode_info *ci, + + enum put_cap_refs_mode { + PUT_CAP_REFS_SYNC = 0, +- PUT_CAP_REFS_NO_CHECK, + PUT_CAP_REFS_ASYNC, + }; + +@@ -3332,11 +3331,6 @@ void ceph_put_cap_refs_async(struct ceph_inode_info *ci, int had) + __ceph_put_cap_refs(ci, had, PUT_CAP_REFS_ASYNC); + } + +-void ceph_put_cap_refs_no_check_caps(struct ceph_inode_info *ci, int had) +-{ +- __ceph_put_cap_refs(ci, had, PUT_CAP_REFS_NO_CHECK); +-} +- + /* + * Release @nr WRBUFFER refs on dirty pages for the given @snapc snap + * context. Adjust per-snap dirty page accounting as appropriate. +diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c +index 558c3af44449c..2eb66dd7d01b2 100644 +--- a/fs/ceph/mds_client.c ++++ b/fs/ceph/mds_client.c +@@ -1089,7 +1089,7 @@ void ceph_mdsc_release_request(struct kref *kref) + struct ceph_mds_request *req = container_of(kref, + struct ceph_mds_request, + r_kref); +- ceph_mdsc_release_dir_caps_no_check(req); ++ ceph_mdsc_release_dir_caps_async(req); + destroy_reply_info(&req->r_reply_info); + if (req->r_request) + ceph_msg_put(req->r_request); +@@ -4247,7 +4247,7 @@ void ceph_mdsc_release_dir_caps(struct ceph_mds_request *req) + } + } + +-void ceph_mdsc_release_dir_caps_no_check(struct ceph_mds_request *req) ++void ceph_mdsc_release_dir_caps_async(struct ceph_mds_request *req) + { + struct ceph_client *cl = req->r_mdsc->fsc->client; + int dcaps; +@@ -4255,8 +4255,7 @@ void ceph_mdsc_release_dir_caps_no_check(struct ceph_mds_request *req) + dcaps = xchg(&req->r_dir_caps, 0); + if (dcaps) { + doutc(cl, "releasing r_dir_caps=%s\n", ceph_cap_string(dcaps)); +- ceph_put_cap_refs_no_check_caps(ceph_inode(req->r_parent), +- dcaps); ++ ceph_put_cap_refs_async(ceph_inode(req->r_parent), dcaps); + } + } + +@@ -4292,7 +4291,7 @@ static void replay_unsafe_requests(struct ceph_mds_client *mdsc, + if (req->r_session->s_mds != session->s_mds) + continue; + +- ceph_mdsc_release_dir_caps_no_check(req); ++ ceph_mdsc_release_dir_caps_async(req); + + __send_request(session, req, true); + } +diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h +index 2e6ddaa13d725..40560af388272 100644 +--- a/fs/ceph/mds_client.h ++++ b/fs/ceph/mds_client.h +@@ -552,7 +552,7 @@ extern int ceph_mdsc_do_request(struct ceph_mds_client *mdsc, + struct inode *dir, + struct ceph_mds_request *req); + extern void ceph_mdsc_release_dir_caps(struct ceph_mds_request *req); +-extern void ceph_mdsc_release_dir_caps_no_check(struct ceph_mds_request *req); ++extern void ceph_mdsc_release_dir_caps_async(struct ceph_mds_request *req); + static inline void ceph_mdsc_get_request(struct ceph_mds_request *req) + { + kref_get(&req->r_kref); +diff --git a/fs/ceph/super.h b/fs/ceph/super.h +index fe0f64a0acb27..15d00bdd92065 100644 +--- a/fs/ceph/super.h ++++ b/fs/ceph/super.h +@@ -1254,8 +1254,6 @@ extern void ceph_take_cap_refs(struct ceph_inode_info *ci, int caps, + extern void ceph_get_cap_refs(struct ceph_inode_info *ci, int caps); + extern void ceph_put_cap_refs(struct ceph_inode_info *ci, int had); + extern void ceph_put_cap_refs_async(struct ceph_inode_info *ci, int had); +-extern void ceph_put_cap_refs_no_check_caps(struct ceph_inode_info *ci, +- int had); + extern void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr, + struct ceph_snap_context *snapc); + extern void __ceph_remove_capsnap(struct inode *inode, +diff --git a/fs/erofs/namei.c b/fs/erofs/namei.c +index d4f631d39f0fa..f0110a78acb20 100644 +--- a/fs/erofs/namei.c ++++ b/fs/erofs/namei.c +@@ -130,24 +130,24 @@ static void *erofs_find_target_block(struct erofs_buf *target, + /* string comparison without already matched prefix */ + diff = erofs_dirnamecmp(name, &dname, &matched); + +- if (!diff) { +- *_ndirents = 0; +- goto out; +- } else if (diff > 0) { +- head = mid + 1; +- startprfx = matched; +- +- if (!IS_ERR(candidate)) +- erofs_put_metabuf(target); +- *target = buf; +- candidate = de; +- *_ndirents = ndirents; +- } else { ++ if (diff < 0) { + erofs_put_metabuf(&buf); +- + back = mid - 1; + endprfx = matched; ++ continue; ++ } ++ ++ if (!IS_ERR(candidate)) ++ erofs_put_metabuf(target); ++ *target = buf; ++ if (!diff) { ++ *_ndirents = 0; ++ return de; + } ++ head = mid + 1; ++ startprfx = matched; ++ candidate = de; ++ *_ndirents = ndirents; + continue; + } + out: /* free if the candidate is valid */ +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 01299b55a567a..fadfca75c3197 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -2229,7 +2229,7 @@ static int ext4_fill_es_cache_info(struct inode *inode, + + + /* +- * ext4_ext_determine_hole - determine hole around given block ++ * ext4_ext_find_hole - find hole around given block according to the given path + * @inode: inode we lookup in + * @path: path in extent tree to @lblk + * @lblk: pointer to logical block around which we want to determine hole +@@ -2241,9 +2241,9 @@ static int ext4_fill_es_cache_info(struct inode *inode, + * The function returns the length of a hole starting at @lblk. We update @lblk + * to the beginning of the hole if we managed to find it. + */ +-static ext4_lblk_t ext4_ext_determine_hole(struct inode *inode, +- struct ext4_ext_path *path, +- ext4_lblk_t *lblk) ++static ext4_lblk_t ext4_ext_find_hole(struct inode *inode, ++ struct ext4_ext_path *path, ++ ext4_lblk_t *lblk) + { + int depth = ext_depth(inode); + struct ext4_extent *ex; +@@ -2270,30 +2270,6 @@ static ext4_lblk_t ext4_ext_determine_hole(struct inode *inode, + return len; + } + +-/* +- * ext4_ext_put_gap_in_cache: +- * calculate boundaries of the gap that the requested block fits into +- * and cache this gap +- */ +-static void +-ext4_ext_put_gap_in_cache(struct inode *inode, ext4_lblk_t hole_start, +- ext4_lblk_t hole_len) +-{ +- struct extent_status es; +- +- ext4_es_find_extent_range(inode, &ext4_es_is_delayed, hole_start, +- hole_start + hole_len - 1, &es); +- if (es.es_len) { +- /* There's delayed extent containing lblock? */ +- if (es.es_lblk <= hole_start) +- return; +- hole_len = min(es.es_lblk - hole_start, hole_len); +- } +- ext_debug(inode, " -> %u:%u\n", hole_start, hole_len); +- ext4_es_insert_extent(inode, hole_start, hole_len, ~0, +- EXTENT_STATUS_HOLE); +-} +- + /* + * ext4_ext_rm_idx: + * removes index from the index block. +@@ -4062,6 +4038,69 @@ static int get_implied_cluster_alloc(struct super_block *sb, + return 0; + } + ++/* ++ * Determine hole length around the given logical block, first try to ++ * locate and expand the hole from the given @path, and then adjust it ++ * if it's partially or completely converted to delayed extents, insert ++ * it into the extent cache tree if it's indeed a hole, finally return ++ * the length of the determined extent. ++ */ ++static ext4_lblk_t ext4_ext_determine_insert_hole(struct inode *inode, ++ struct ext4_ext_path *path, ++ ext4_lblk_t lblk) ++{ ++ ext4_lblk_t hole_start, len; ++ struct extent_status es; ++ ++ hole_start = lblk; ++ len = ext4_ext_find_hole(inode, path, &hole_start); ++again: ++ ext4_es_find_extent_range(inode, &ext4_es_is_delayed, hole_start, ++ hole_start + len - 1, &es); ++ if (!es.es_len) ++ goto insert_hole; ++ ++ /* ++ * There's a delalloc extent in the hole, handle it if the delalloc ++ * extent is in front of, behind and straddle the queried range. ++ */ ++ if (lblk >= es.es_lblk + es.es_len) { ++ /* ++ * The delalloc extent is in front of the queried range, ++ * find again from the queried start block. ++ */ ++ len -= lblk - hole_start; ++ hole_start = lblk; ++ goto again; ++ } else if (in_range(lblk, es.es_lblk, es.es_len)) { ++ /* ++ * The delalloc extent containing lblk, it must have been ++ * added after ext4_map_blocks() checked the extent status ++ * tree, adjust the length to the delalloc extent's after ++ * lblk. ++ */ ++ len = es.es_lblk + es.es_len - lblk; ++ return len; ++ } else { ++ /* ++ * The delalloc extent is partially or completely behind ++ * the queried range, update hole length until the ++ * beginning of the delalloc extent. ++ */ ++ len = min(es.es_lblk - hole_start, len); ++ } ++ ++insert_hole: ++ /* Put just found gap into cache to speed up subsequent requests */ ++ ext_debug(inode, " -> %u:%u\n", hole_start, len); ++ ext4_es_insert_extent(inode, hole_start, len, ~0, EXTENT_STATUS_HOLE); ++ ++ /* Update hole_len to reflect hole size after lblk */ ++ if (hole_start != lblk) ++ len -= lblk - hole_start; ++ ++ return len; ++} + + /* + * Block allocation/map/preallocation routine for extents based files +@@ -4179,22 +4218,12 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, + * we couldn't try to create block if create flag is zero + */ + if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) { +- ext4_lblk_t hole_start, hole_len; ++ ext4_lblk_t len; + +- hole_start = map->m_lblk; +- hole_len = ext4_ext_determine_hole(inode, path, &hole_start); +- /* +- * put just found gap into cache to speed up +- * subsequent requests +- */ +- ext4_ext_put_gap_in_cache(inode, hole_start, hole_len); ++ len = ext4_ext_determine_insert_hole(inode, path, map->m_lblk); + +- /* Update hole_len to reflect hole size after map->m_lblk */ +- if (hole_start != map->m_lblk) +- hole_len -= map->m_lblk - hole_start; + map->m_pblk = 0; +- map->m_len = min_t(unsigned int, map->m_len, hole_len); +- ++ map->m_len = min_t(unsigned int, map->m_len, len); + goto out; + } + +diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c +index be63744c95d3b..7497a789d002e 100644 +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -842,7 +842,7 @@ 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; + +- if (!test_opt2(sb, MB_OPTIMIZE_SCAN) || grp->bb_free == 0) ++ if (!test_opt2(sb, MB_OPTIMIZE_SCAN) || grp->bb_fragments == 0) + return; + + new_order = mb_avg_fragment_size_order(sb, +@@ -2305,6 +2305,9 @@ void ext4_mb_try_best_found(struct ext4_allocation_context *ac, + return; + + ext4_lock_group(ac->ac_sb, group); ++ if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info))) ++ goto out; ++ + max = mb_find_extent(e4b, ex.fe_start, ex.fe_len, &ex); + + if (max > 0) { +@@ -2312,6 +2315,7 @@ void ext4_mb_try_best_found(struct ext4_allocation_context *ac, + ext4_mb_use_best_found(ac, e4b); + } + ++out: + ext4_unlock_group(ac->ac_sb, group); + ext4_mb_unload_buddy(e4b); + } +@@ -2338,12 +2342,10 @@ int ext4_mb_find_by_goal(struct ext4_allocation_context *ac, + if (err) + return err; + +- if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info))) { +- ext4_mb_unload_buddy(e4b); +- return 0; +- } +- + ext4_lock_group(ac->ac_sb, group); ++ if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info))) ++ goto out; ++ + max = mb_find_extent(e4b, ac->ac_g_ex.fe_start, + ac->ac_g_ex.fe_len, &ex); + ex.fe_logical = 0xDEADFA11; /* debug value */ +@@ -2376,6 +2378,7 @@ int ext4_mb_find_by_goal(struct ext4_allocation_context *ac, + ac->ac_b_ex = ex; + ext4_mb_use_best_found(ac, e4b); + } ++out: + ext4_unlock_group(ac->ac_sb, group); + ext4_mb_unload_buddy(e4b); + +diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c +index 63f70259edc0d..7aadf50109994 100644 +--- a/fs/ntfs3/attrib.c ++++ b/fs/ntfs3/attrib.c +@@ -886,7 +886,7 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn, + struct runs_tree *run = &ni->file.run; + struct ntfs_sb_info *sbi; + u8 cluster_bits; +- struct ATTRIB *attr = NULL, *attr_b; ++ struct ATTRIB *attr, *attr_b; + struct ATTR_LIST_ENTRY *le, *le_b; + struct mft_inode *mi, *mi_b; + CLST hint, svcn, to_alloc, evcn1, next_svcn, asize, end, vcn0, alen; +@@ -904,12 +904,8 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn, + *len = 0; + up_read(&ni->file.run_lock); + +- if (*len) { +- if (*lcn != SPARSE_LCN || !new) +- return 0; /* Fast normal way without allocation. */ +- else if (clen > *len) +- clen = *len; +- } ++ if (*len && (*lcn != SPARSE_LCN || !new)) ++ return 0; /* Fast normal way without allocation. */ + + /* No cluster in cache or we need to allocate cluster in hole. */ + sbi = ni->mi.sbi; +@@ -918,6 +914,17 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn, + ni_lock(ni); + down_write(&ni->file.run_lock); + ++ /* Repeat the code above (under write lock). */ ++ if (!run_lookup_entry(run, vcn, lcn, len, NULL)) ++ *len = 0; ++ ++ if (*len) { ++ if (*lcn != SPARSE_LCN || !new) ++ goto out; /* normal way without allocation. */ ++ if (clen > *len) ++ clen = *len; ++ } ++ + le_b = NULL; + attr_b = ni_find_attr(ni, NULL, &le_b, ATTR_DATA, NULL, 0, NULL, &mi_b); + if (!attr_b) { +@@ -1736,8 +1743,10 @@ int attr_allocate_frame(struct ntfs_inode *ni, CLST frame, size_t compr_size, + le_b = NULL; + attr_b = ni_find_attr(ni, NULL, &le_b, ATTR_DATA, NULL, + 0, NULL, &mi_b); +- if (!attr_b) +- return -ENOENT; ++ if (!attr_b) { ++ err = -ENOENT; ++ goto out; ++ } + + attr = attr_b; + le = le_b; +@@ -1818,13 +1827,15 @@ int attr_allocate_frame(struct ntfs_inode *ni, CLST frame, size_t compr_size, + ok: + run_truncate_around(run, vcn); + out: +- if (new_valid > data_size) +- new_valid = data_size; ++ if (attr_b) { ++ if (new_valid > data_size) ++ new_valid = data_size; + +- valid_size = le64_to_cpu(attr_b->nres.valid_size); +- if (new_valid != valid_size) { +- attr_b->nres.valid_size = cpu_to_le64(valid_size); +- mi_b->dirty = true; ++ valid_size = le64_to_cpu(attr_b->nres.valid_size); ++ if (new_valid != valid_size) { ++ attr_b->nres.valid_size = cpu_to_le64(valid_size); ++ mi_b->dirty = true; ++ } + } + + return err; +@@ -2073,7 +2084,7 @@ int attr_collapse_range(struct ntfs_inode *ni, u64 vbo, u64 bytes) + + /* Update inode size. */ + ni->i_valid = valid_size; +- ni->vfs_inode.i_size = data_size; ++ i_size_write(&ni->vfs_inode, data_size); + inode_set_bytes(&ni->vfs_inode, total_size); + ni->ni_flags |= NI_FLAG_UPDATE_PARENT; + mark_inode_dirty(&ni->vfs_inode); +@@ -2488,7 +2499,7 @@ int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes) + mi_b->dirty = true; + + done: +- ni->vfs_inode.i_size += bytes; ++ i_size_write(&ni->vfs_inode, ni->vfs_inode.i_size + bytes); + ni->ni_flags |= NI_FLAG_UPDATE_PARENT; + mark_inode_dirty(&ni->vfs_inode); + +diff --git a/fs/ntfs3/attrlist.c b/fs/ntfs3/attrlist.c +index 7c01735d1219d..9f4bd8d260901 100644 +--- a/fs/ntfs3/attrlist.c ++++ b/fs/ntfs3/attrlist.c +@@ -29,7 +29,7 @@ static inline bool al_is_valid_le(const struct ntfs_inode *ni, + void al_destroy(struct ntfs_inode *ni) + { + run_close(&ni->attr_list.run); +- kfree(ni->attr_list.le); ++ kvfree(ni->attr_list.le); + ni->attr_list.le = NULL; + ni->attr_list.size = 0; + ni->attr_list.dirty = false; +@@ -127,12 +127,13 @@ struct ATTR_LIST_ENTRY *al_enumerate(struct ntfs_inode *ni, + { + size_t off; + u16 sz; ++ const unsigned le_min_size = le_size(0); + + if (!le) { + le = ni->attr_list.le; + } else { + sz = le16_to_cpu(le->size); +- if (sz < sizeof(struct ATTR_LIST_ENTRY)) { ++ if (sz < le_min_size) { + /* Impossible 'cause we should not return such le. */ + return NULL; + } +@@ -141,7 +142,7 @@ struct ATTR_LIST_ENTRY *al_enumerate(struct ntfs_inode *ni, + + /* Check boundary. */ + off = PtrOffset(ni->attr_list.le, le); +- if (off + sizeof(struct ATTR_LIST_ENTRY) > ni->attr_list.size) { ++ if (off + le_min_size > ni->attr_list.size) { + /* The regular end of list. */ + return NULL; + } +@@ -149,8 +150,7 @@ struct ATTR_LIST_ENTRY *al_enumerate(struct ntfs_inode *ni, + sz = le16_to_cpu(le->size); + + /* Check le for errors. */ +- if (sz < sizeof(struct ATTR_LIST_ENTRY) || +- off + sz > ni->attr_list.size || ++ if (sz < le_min_size || off + sz > ni->attr_list.size || + sz < le->name_off + le->name_len * sizeof(short)) { + return NULL; + } +@@ -318,7 +318,7 @@ int al_add_le(struct ntfs_inode *ni, enum ATTR_TYPE type, const __le16 *name, + memcpy(ptr, al->le, off); + memcpy(Add2Ptr(ptr, off + sz), le, old_size - off); + le = Add2Ptr(ptr, off); +- kfree(al->le); ++ kvfree(al->le); + al->le = ptr; + } else { + memmove(Add2Ptr(le, sz), le, old_size - off); +diff --git a/fs/ntfs3/bitmap.c b/fs/ntfs3/bitmap.c +index 63f14a0232f6a..845f9b22deef0 100644 +--- a/fs/ntfs3/bitmap.c ++++ b/fs/ntfs3/bitmap.c +@@ -124,7 +124,7 @@ void wnd_close(struct wnd_bitmap *wnd) + { + struct rb_node *node, *next; + +- kfree(wnd->free_bits); ++ kvfree(wnd->free_bits); + wnd->free_bits = NULL; + run_close(&wnd->run); + +@@ -1360,7 +1360,7 @@ int wnd_extend(struct wnd_bitmap *wnd, size_t new_bits) + memcpy(new_free, wnd->free_bits, wnd->nwnd * sizeof(short)); + memset(new_free + wnd->nwnd, 0, + (new_wnd - wnd->nwnd) * sizeof(short)); +- kfree(wnd->free_bits); ++ kvfree(wnd->free_bits); + wnd->free_bits = new_free; + } + +diff --git a/fs/ntfs3/dir.c b/fs/ntfs3/dir.c +index ec0566b322d5d..effa6accf8a85 100644 +--- a/fs/ntfs3/dir.c ++++ b/fs/ntfs3/dir.c +@@ -309,11 +309,31 @@ static inline int ntfs_filldir(struct ntfs_sb_info *sbi, struct ntfs_inode *ni, + return 0; + } + +- /* NTFS: symlinks are "dir + reparse" or "file + reparse" */ +- if (fname->dup.fa & FILE_ATTRIBUTE_REPARSE_POINT) +- dt_type = DT_LNK; +- else +- dt_type = (fname->dup.fa & FILE_ATTRIBUTE_DIRECTORY) ? DT_DIR : DT_REG; ++ /* ++ * NTFS: symlinks are "dir + reparse" or "file + reparse" ++ * Unfortunately reparse attribute is used for many purposes (several dozens). ++ * It is not possible here to know is this name symlink or not. ++ * To get exactly the type of name we should to open inode (read mft). ++ * getattr for opened file (fstat) correctly returns symlink. ++ */ ++ dt_type = (fname->dup.fa & FILE_ATTRIBUTE_DIRECTORY) ? DT_DIR : DT_REG; ++ ++ /* ++ * It is not reliable to detect the type of name using duplicated information ++ * stored in parent directory. ++ * The only correct way to get the type of name - read MFT record and find ATTR_STD. ++ * The code below is not good idea. ++ * It does additional locks/reads just to get the type of name. ++ * Should we use additional mount option to enable branch below? ++ */ ++ if ((fname->dup.fa & FILE_ATTRIBUTE_REPARSE_POINT) && ++ ino != ni->mi.rno) { ++ struct inode *inode = ntfs_iget5(sbi->sb, &e->ref, NULL); ++ if (!IS_ERR_OR_NULL(inode)) { ++ dt_type = fs_umode_to_dtype(inode->i_mode); ++ iput(inode); ++ } ++ } + + return !dir_emit(ctx, (s8 *)name, name_len, ino, dt_type); + } +@@ -495,11 +515,9 @@ static int ntfs_dir_count(struct inode *dir, bool *is_empty, size_t *dirs, + struct INDEX_HDR *hdr; + const struct ATTR_FILE_NAME *fname; + u32 e_size, off, end; +- u64 vbo = 0; + size_t drs = 0, fles = 0, bit = 0; +- loff_t i_size = ni->vfs_inode.i_size; + struct indx_node *node = NULL; +- u8 index_bits = ni->dir.index_bits; ++ size_t max_indx = i_size_read(&ni->vfs_inode) >> ni->dir.index_bits; + + if (is_empty) + *is_empty = true; +@@ -518,8 +536,10 @@ static int ntfs_dir_count(struct inode *dir, bool *is_empty, size_t *dirs, + e = Add2Ptr(hdr, off); + e_size = le16_to_cpu(e->size); + if (e_size < sizeof(struct NTFS_DE) || +- off + e_size > end) ++ off + e_size > end) { ++ /* Looks like corruption. */ + break; ++ } + + if (de_is_last(e)) + break; +@@ -543,7 +563,7 @@ static int ntfs_dir_count(struct inode *dir, bool *is_empty, size_t *dirs, + fles += 1; + } + +- if (vbo >= i_size) ++ if (bit >= max_indx) + goto out; + + err = indx_used_bit(&ni->dir, ni, &bit); +@@ -553,8 +573,7 @@ static int ntfs_dir_count(struct inode *dir, bool *is_empty, size_t *dirs, + if (bit == MINUS_ONE_T) + goto out; + +- vbo = (u64)bit << index_bits; +- if (vbo >= i_size) ++ if (bit >= max_indx) + goto out; + + err = indx_read(&ni->dir, ni, bit << ni->dir.idx2vbn_bits, +@@ -564,7 +583,6 @@ static int ntfs_dir_count(struct inode *dir, bool *is_empty, size_t *dirs, + + hdr = &node->index->ihdr; + bit += 1; +- vbo = (u64)bit << ni->dir.idx2vbn_bits; + } + + out: +diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c +index a5a30a24ce5df..691b0c9b95ae7 100644 +--- a/fs/ntfs3/file.c ++++ b/fs/ntfs3/file.c +@@ -188,6 +188,7 @@ static int ntfs_zero_range(struct inode *inode, u64 vbo, u64 vbo_to) + u32 bh_next, bh_off, to; + sector_t iblock; + struct folio *folio; ++ bool dirty = false; + + for (; idx < idx_end; idx += 1, from = 0) { + page_off = (loff_t)idx << PAGE_SHIFT; +@@ -223,29 +224,27 @@ static int ntfs_zero_range(struct inode *inode, u64 vbo, u64 vbo_to) + /* Ok, it's mapped. Make sure it's up-to-date. */ + if (folio_test_uptodate(folio)) + set_buffer_uptodate(bh); +- +- if (!buffer_uptodate(bh)) { +- err = bh_read(bh, 0); +- if (err < 0) { +- folio_unlock(folio); +- folio_put(folio); +- goto out; +- } ++ else if (bh_read(bh, 0) < 0) { ++ err = -EIO; ++ folio_unlock(folio); ++ folio_put(folio); ++ goto out; + } + + mark_buffer_dirty(bh); +- + } while (bh_off = bh_next, iblock += 1, + head != (bh = bh->b_this_page)); + + folio_zero_segment(folio, from, to); ++ dirty = true; + + folio_unlock(folio); + folio_put(folio); + cond_resched(); + } + out: +- mark_inode_dirty(inode); ++ if (dirty) ++ mark_inode_dirty(inode); + return err; + } + +@@ -261,6 +260,9 @@ static int ntfs_file_mmap(struct file *file, struct vm_area_struct *vma) + bool rw = vma->vm_flags & VM_WRITE; + int err; + ++ if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) ++ return -EIO; ++ + if (is_encrypted(ni)) { + ntfs_inode_warn(inode, "mmap encrypted not supported"); + return -EOPNOTSUPP; +@@ -499,10 +501,14 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len) + ni_lock(ni); + err = attr_punch_hole(ni, vbo, len, &frame_size); + ni_unlock(ni); ++ if (!err) ++ goto ok; ++ + if (err != E_NTFS_NOTALIGNED) + goto out; + + /* Process not aligned punch. */ ++ err = 0; + mask = frame_size - 1; + vbo_a = (vbo + mask) & ~mask; + end_a = end & ~mask; +@@ -525,6 +531,8 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len) + ni_lock(ni); + err = attr_punch_hole(ni, vbo_a, end_a - vbo_a, NULL); + ni_unlock(ni); ++ if (err) ++ goto out; + } + } else if (mode & FALLOC_FL_COLLAPSE_RANGE) { + /* +@@ -564,6 +572,8 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len) + ni_lock(ni); + err = attr_insert_range(ni, vbo, len); + ni_unlock(ni); ++ if (err) ++ goto out; + } else { + /* Check new size. */ + u8 cluster_bits = sbi->cluster_bits; +@@ -633,11 +643,18 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len) + &ni->file.run, i_size, &ni->i_valid, + true, NULL); + ni_unlock(ni); ++ if (err) ++ goto out; + } else if (new_size > i_size) { +- inode->i_size = new_size; ++ i_size_write(inode, new_size); + } + } + ++ok: ++ err = file_modified(file); ++ if (err) ++ goto out; ++ + out: + if (map_locked) + filemap_invalidate_unlock(mapping); +@@ -663,6 +680,9 @@ int ntfs3_setattr(struct mnt_idmap *idmap, struct dentry *dentry, + umode_t mode = inode->i_mode; + int err; + ++ if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) ++ return -EIO; ++ + err = setattr_prepare(idmap, dentry, attr); + if (err) + goto out; +@@ -676,7 +696,7 @@ int ntfs3_setattr(struct mnt_idmap *idmap, struct dentry *dentry, + goto out; + } + inode_dio_wait(inode); +- oldsize = inode->i_size; ++ oldsize = i_size_read(inode); + newsize = attr->ia_size; + + if (newsize <= oldsize) +@@ -688,7 +708,7 @@ int ntfs3_setattr(struct mnt_idmap *idmap, struct dentry *dentry, + goto out; + + ni->ni_flags |= NI_FLAG_UPDATE_PARENT; +- inode->i_size = newsize; ++ i_size_write(inode, newsize); + } + + setattr_copy(idmap, inode, attr); +@@ -718,6 +738,9 @@ static ssize_t ntfs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) + struct inode *inode = file->f_mapping->host; + struct ntfs_inode *ni = ntfs_i(inode); + ++ if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) ++ return -EIO; ++ + if (is_encrypted(ni)) { + ntfs_inode_warn(inode, "encrypted i/o not supported"); + return -EOPNOTSUPP; +@@ -752,6 +775,9 @@ static ssize_t ntfs_file_splice_read(struct file *in, loff_t *ppos, + struct inode *inode = in->f_mapping->host; + struct ntfs_inode *ni = ntfs_i(inode); + ++ if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) ++ return -EIO; ++ + if (is_encrypted(ni)) { + ntfs_inode_warn(inode, "encrypted i/o not supported"); + return -EOPNOTSUPP; +@@ -821,7 +847,7 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) + size_t count = iov_iter_count(from); + loff_t pos = iocb->ki_pos; + struct inode *inode = file_inode(file); +- loff_t i_size = inode->i_size; ++ loff_t i_size = i_size_read(inode); + struct address_space *mapping = inode->i_mapping; + struct ntfs_inode *ni = ntfs_i(inode); + u64 valid = ni->i_valid; +@@ -1028,6 +1054,8 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) + iocb->ki_pos += written; + if (iocb->ki_pos > ni->i_valid) + ni->i_valid = iocb->ki_pos; ++ if (iocb->ki_pos > i_size) ++ i_size_write(inode, iocb->ki_pos); + + return written; + } +@@ -1041,8 +1069,12 @@ static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) + struct address_space *mapping = file->f_mapping; + struct inode *inode = mapping->host; + ssize_t ret; ++ int err; + struct ntfs_inode *ni = ntfs_i(inode); + ++ if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) ++ return -EIO; ++ + if (is_encrypted(ni)) { + ntfs_inode_warn(inode, "encrypted i/o not supported"); + return -EOPNOTSUPP; +@@ -1068,6 +1100,12 @@ static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) + if (ret <= 0) + goto out; + ++ err = file_modified(iocb->ki_filp); ++ if (err) { ++ ret = err; ++ goto out; ++ } ++ + if (WARN_ON(ni->ni_flags & NI_FLAG_COMPRESSED_MASK)) { + /* Should never be here, see ntfs_file_open(). */ + ret = -EOPNOTSUPP; +@@ -1097,6 +1135,9 @@ int ntfs_file_open(struct inode *inode, struct file *file) + { + struct ntfs_inode *ni = ntfs_i(inode); + ++ if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) ++ return -EIO; ++ + if (unlikely((is_compressed(ni) || is_encrypted(ni)) && + (file->f_flags & O_DIRECT))) { + return -EOPNOTSUPP; +@@ -1138,7 +1179,8 @@ static int ntfs_file_release(struct inode *inode, struct file *file) + down_write(&ni->file.run_lock); + + err = attr_set_size(ni, ATTR_DATA, NULL, 0, &ni->file.run, +- inode->i_size, &ni->i_valid, false, NULL); ++ i_size_read(inode), &ni->i_valid, false, ++ NULL); + + up_write(&ni->file.run_lock); + ni_unlock(ni); +diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c +index 3df2d9e34b914..3b42938a9d3b2 100644 +--- a/fs/ntfs3/frecord.c ++++ b/fs/ntfs3/frecord.c +@@ -778,7 +778,7 @@ static int ni_try_remove_attr_list(struct ntfs_inode *ni) + run_deallocate(sbi, &ni->attr_list.run, true); + run_close(&ni->attr_list.run); + ni->attr_list.size = 0; +- kfree(ni->attr_list.le); ++ kvfree(ni->attr_list.le); + ni->attr_list.le = NULL; + ni->attr_list.dirty = false; + +@@ -927,7 +927,7 @@ int ni_create_attr_list(struct ntfs_inode *ni) + return 0; + + out: +- kfree(ni->attr_list.le); ++ kvfree(ni->attr_list.le); + ni->attr_list.le = NULL; + ni->attr_list.size = 0; + return err; +@@ -2099,7 +2099,7 @@ int ni_readpage_cmpr(struct ntfs_inode *ni, struct page *page) + gfp_t gfp_mask; + struct page *pg; + +- if (vbo >= ni->vfs_inode.i_size) { ++ if (vbo >= i_size_read(&ni->vfs_inode)) { + SetPageUptodate(page); + err = 0; + goto out; +@@ -2173,7 +2173,7 @@ int ni_decompress_file(struct ntfs_inode *ni) + { + struct ntfs_sb_info *sbi = ni->mi.sbi; + struct inode *inode = &ni->vfs_inode; +- loff_t i_size = inode->i_size; ++ loff_t i_size = i_size_read(inode); + struct address_space *mapping = inode->i_mapping; + gfp_t gfp_mask = mapping_gfp_mask(mapping); + struct page **pages = NULL; +@@ -2457,6 +2457,7 @@ int ni_read_frame(struct ntfs_inode *ni, u64 frame_vbo, struct page **pages, + struct ATTR_LIST_ENTRY *le = NULL; + struct runs_tree *run = &ni->file.run; + u64 valid_size = ni->i_valid; ++ loff_t i_size = i_size_read(&ni->vfs_inode); + u64 vbo_disk; + size_t unc_size; + u32 frame_size, i, npages_disk, ondisk_size; +@@ -2548,7 +2549,7 @@ int ni_read_frame(struct ntfs_inode *ni, u64 frame_vbo, struct page **pages, + } + } + +- frames = (ni->vfs_inode.i_size - 1) >> frame_bits; ++ frames = (i_size - 1) >> frame_bits; + + err = attr_wof_frame_info(ni, attr, run, frame64, frames, + frame_bits, &ondisk_size, &vbo_data); +@@ -2556,8 +2557,7 @@ int ni_read_frame(struct ntfs_inode *ni, u64 frame_vbo, struct page **pages, + goto out2; + + if (frame64 == frames) { +- unc_size = 1 + ((ni->vfs_inode.i_size - 1) & +- (frame_size - 1)); ++ unc_size = 1 + ((i_size - 1) & (frame_size - 1)); + ondisk_size = attr_size(attr) - vbo_data; + } else { + unc_size = frame_size; +@@ -3259,6 +3259,9 @@ int ni_write_inode(struct inode *inode, int sync, const char *hint) + if (is_bad_inode(inode) || sb_rdonly(sb)) + return 0; + ++ if (unlikely(ntfs3_forced_shutdown(sb))) ++ return -EIO; ++ + if (!ni_trylock(ni)) { + /* 'ni' is under modification, skip for now. */ + mark_inode_dirty_sync(inode); +@@ -3288,7 +3291,7 @@ int ni_write_inode(struct inode *inode, int sync, const char *hint) + modified = true; + } + +- ts = inode_get_mtime(inode); ++ ts = inode_get_ctime(inode); + dup.c_time = kernel2nt(&ts); + if (std->c_time != dup.c_time) { + std->c_time = dup.c_time; +diff --git a/fs/ntfs3/fslog.c b/fs/ntfs3/fslog.c +index 98ccb66508583..855519713bf79 100644 +--- a/fs/ntfs3/fslog.c ++++ b/fs/ntfs3/fslog.c +@@ -465,7 +465,7 @@ static inline bool is_rst_area_valid(const struct RESTART_HDR *rhdr) + { + const struct RESTART_AREA *ra; + u16 cl, fl, ul; +- u32 off, l_size, file_dat_bits, file_size_round; ++ u32 off, l_size, seq_bits; + u16 ro = le16_to_cpu(rhdr->ra_off); + u32 sys_page = le32_to_cpu(rhdr->sys_page_size); + +@@ -511,13 +511,15 @@ static inline bool is_rst_area_valid(const struct RESTART_HDR *rhdr) + /* Make sure the sequence number bits match the log file size. */ + l_size = le64_to_cpu(ra->l_size); + +- file_dat_bits = sizeof(u64) * 8 - le32_to_cpu(ra->seq_num_bits); +- file_size_round = 1u << (file_dat_bits + 3); +- if (file_size_round != l_size && +- (file_size_round < l_size || (file_size_round / 2) > l_size)) { +- return false; ++ seq_bits = sizeof(u64) * 8 + 3; ++ while (l_size) { ++ l_size >>= 1; ++ seq_bits -= 1; + } + ++ if (seq_bits != ra->seq_num_bits) ++ return false; ++ + /* The log page data offset and record header length must be quad-aligned. */ + if (!IS_ALIGNED(le16_to_cpu(ra->data_off), 8) || + !IS_ALIGNED(le16_to_cpu(ra->rec_hdr_len), 8)) +@@ -974,6 +976,16 @@ static inline void *alloc_rsttbl_from_idx(struct RESTART_TABLE **tbl, u32 vbo) + return e; + } + ++struct restart_info { ++ u64 last_lsn; ++ struct RESTART_HDR *r_page; ++ u32 vbo; ++ bool chkdsk_was_run; ++ bool valid_page; ++ bool initialized; ++ bool restart; ++}; ++ + #define RESTART_SINGLE_PAGE_IO cpu_to_le16(0x0001) + + #define NTFSLOG_WRAPPED 0x00000001 +@@ -987,6 +999,7 @@ struct ntfs_log { + struct ntfs_inode *ni; + + u32 l_size; ++ u32 orig_file_size; + u32 sys_page_size; + u32 sys_page_mask; + u32 page_size; +@@ -1040,6 +1053,8 @@ struct ntfs_log { + + struct CLIENT_ID client_id; + u32 client_undo_commit; ++ ++ struct restart_info rst_info, rst_info2; + }; + + static inline u32 lsn_to_vbo(struct ntfs_log *log, const u64 lsn) +@@ -1105,16 +1120,6 @@ static inline bool verify_client_lsn(struct ntfs_log *log, + lsn <= le64_to_cpu(log->ra->current_lsn) && lsn; + } + +-struct restart_info { +- u64 last_lsn; +- struct RESTART_HDR *r_page; +- u32 vbo; +- bool chkdsk_was_run; +- bool valid_page; +- bool initialized; +- bool restart; +-}; +- + static int read_log_page(struct ntfs_log *log, u32 vbo, + struct RECORD_PAGE_HDR **buffer, bool *usa_error) + { +@@ -1176,7 +1181,7 @@ static int read_log_page(struct ntfs_log *log, u32 vbo, + * restart page header. It will stop the first time we find a + * valid page header. + */ +-static int log_read_rst(struct ntfs_log *log, u32 l_size, bool first, ++static int log_read_rst(struct ntfs_log *log, bool first, + struct restart_info *info) + { + u32 skip, vbo; +@@ -1192,7 +1197,7 @@ static int log_read_rst(struct ntfs_log *log, u32 l_size, bool first, + } + + /* Loop continuously until we succeed. */ +- for (; vbo < l_size; vbo = 2 * vbo + skip, skip = 0) { ++ for (; vbo < log->l_size; vbo = 2 * vbo + skip, skip = 0) { + bool usa_error; + bool brst, bchk; + struct RESTART_AREA *ra; +@@ -1285,22 +1290,17 @@ static int log_read_rst(struct ntfs_log *log, u32 l_size, bool first, + /* + * Ilog_init_pg_hdr - Init @log from restart page header. + */ +-static void log_init_pg_hdr(struct ntfs_log *log, u32 sys_page_size, +- u32 page_size, u16 major_ver, u16 minor_ver) ++static void log_init_pg_hdr(struct ntfs_log *log, u16 major_ver, u16 minor_ver) + { +- log->sys_page_size = sys_page_size; +- log->sys_page_mask = sys_page_size - 1; +- log->page_size = page_size; +- log->page_mask = page_size - 1; +- log->page_bits = blksize_bits(page_size); ++ log->sys_page_size = log->page_size; ++ log->sys_page_mask = log->page_mask; + + log->clst_per_page = log->page_size >> log->ni->mi.sbi->cluster_bits; + if (!log->clst_per_page) + log->clst_per_page = 1; + +- log->first_page = major_ver >= 2 ? +- 0x22 * page_size : +- ((sys_page_size << 1) + (page_size << 1)); ++ log->first_page = major_ver >= 2 ? 0x22 * log->page_size : ++ 4 * log->page_size; + log->major_ver = major_ver; + log->minor_ver = minor_ver; + } +@@ -1308,12 +1308,11 @@ static void log_init_pg_hdr(struct ntfs_log *log, u32 sys_page_size, + /* + * log_create - Init @log in cases when we don't have a restart area to use. + */ +-static void log_create(struct ntfs_log *log, u32 l_size, const u64 last_lsn, ++static void log_create(struct ntfs_log *log, const u64 last_lsn, + u32 open_log_count, bool wrapped, bool use_multi_page) + { +- log->l_size = l_size; + /* All file offsets must be quadword aligned. */ +- log->file_data_bits = blksize_bits(l_size) - 3; ++ log->file_data_bits = blksize_bits(log->l_size) - 3; + log->seq_num_mask = (8 << log->file_data_bits) - 1; + log->seq_num_bits = sizeof(u64) * 8 - log->file_data_bits; + log->seq_num = (last_lsn >> log->file_data_bits) + 2; +@@ -3720,10 +3719,8 @@ int log_replay(struct ntfs_inode *ni, bool *initialized) + struct ntfs_sb_info *sbi = ni->mi.sbi; + struct ntfs_log *log; + +- struct restart_info rst_info, rst_info2; +- u64 rec_lsn, ra_lsn, checkpt_lsn = 0, rlsn = 0; ++ u64 rec_lsn, checkpt_lsn = 0, rlsn = 0; + struct ATTR_NAME_ENTRY *attr_names = NULL; +- struct ATTR_NAME_ENTRY *ane; + struct RESTART_TABLE *dptbl = NULL; + struct RESTART_TABLE *trtbl = NULL; + const struct RESTART_TABLE *rt; +@@ -3741,9 +3738,7 @@ int log_replay(struct ntfs_inode *ni, bool *initialized) + struct TRANSACTION_ENTRY *tr; + struct DIR_PAGE_ENTRY *dp; + u32 i, bytes_per_attr_entry; +- u32 l_size = ni->vfs_inode.i_size; +- u32 orig_file_size = l_size; +- u32 page_size, vbo, tail, off, dlen; ++ u32 vbo, tail, off, dlen; + u32 saved_len, rec_len, transact_id; + bool use_second_page; + struct RESTART_AREA *ra2, *ra = NULL; +@@ -3758,52 +3753,50 @@ int log_replay(struct ntfs_inode *ni, bool *initialized) + u16 t16; + u32 t32; + +- /* Get the size of page. NOTE: To replay we can use default page. */ +-#if PAGE_SIZE >= DefaultLogPageSize && PAGE_SIZE <= DefaultLogPageSize * 2 +- page_size = norm_file_page(PAGE_SIZE, &l_size, true); +-#else +- page_size = norm_file_page(PAGE_SIZE, &l_size, false); +-#endif +- if (!page_size) +- return -EINVAL; +- + log = kzalloc(sizeof(struct ntfs_log), GFP_NOFS); + if (!log) + return -ENOMEM; + + log->ni = ni; +- log->l_size = l_size; +- log->one_page_buf = kmalloc(page_size, GFP_NOFS); ++ log->l_size = log->orig_file_size = ni->vfs_inode.i_size; + ++ /* Get the size of page. NOTE: To replay we can use default page. */ ++#if PAGE_SIZE >= DefaultLogPageSize && PAGE_SIZE <= DefaultLogPageSize * 2 ++ log->page_size = norm_file_page(PAGE_SIZE, &log->l_size, true); ++#else ++ log->page_size = norm_file_page(PAGE_SIZE, &log->l_size, false); ++#endif ++ if (!log->page_size) { ++ err = -EINVAL; ++ goto out; ++ } ++ ++ log->one_page_buf = kmalloc(log->page_size, GFP_NOFS); + if (!log->one_page_buf) { + err = -ENOMEM; + goto out; + } + +- log->page_size = page_size; +- log->page_mask = page_size - 1; +- log->page_bits = blksize_bits(page_size); ++ log->page_mask = log->page_size - 1; ++ log->page_bits = blksize_bits(log->page_size); + + /* Look for a restart area on the disk. */ +- memset(&rst_info, 0, sizeof(struct restart_info)); +- err = log_read_rst(log, l_size, true, &rst_info); ++ err = log_read_rst(log, true, &log->rst_info); + if (err) + goto out; + + /* remember 'initialized' */ +- *initialized = rst_info.initialized; ++ *initialized = log->rst_info.initialized; + +- if (!rst_info.restart) { +- if (rst_info.initialized) { ++ if (!log->rst_info.restart) { ++ if (log->rst_info.initialized) { + /* No restart area but the file is not initialized. */ + err = -EINVAL; + goto out; + } + +- log_init_pg_hdr(log, page_size, page_size, 1, 1); +- log_create(log, l_size, 0, get_random_u32(), false, false); +- +- log->ra = ra; ++ log_init_pg_hdr(log, 1, 1); ++ log_create(log, 0, get_random_u32(), false, false); + + ra = log_create_ra(log); + if (!ra) { +@@ -3820,25 +3813,26 @@ int log_replay(struct ntfs_inode *ni, bool *initialized) + * If the restart offset above wasn't zero then we won't + * look for a second restart. + */ +- if (rst_info.vbo) ++ if (log->rst_info.vbo) + goto check_restart_area; + +- memset(&rst_info2, 0, sizeof(struct restart_info)); +- err = log_read_rst(log, l_size, false, &rst_info2); ++ err = log_read_rst(log, false, &log->rst_info2); + if (err) + goto out; + + /* Determine which restart area to use. */ +- if (!rst_info2.restart || rst_info2.last_lsn <= rst_info.last_lsn) ++ if (!log->rst_info2.restart || ++ log->rst_info2.last_lsn <= log->rst_info.last_lsn) + goto use_first_page; + + use_second_page = true; + +- if (rst_info.chkdsk_was_run && page_size != rst_info.vbo) { ++ if (log->rst_info.chkdsk_was_run && ++ log->page_size != log->rst_info.vbo) { + struct RECORD_PAGE_HDR *sp = NULL; + bool usa_error; + +- if (!read_log_page(log, page_size, &sp, &usa_error) && ++ if (!read_log_page(log, log->page_size, &sp, &usa_error) && + sp->rhdr.sign == NTFS_CHKD_SIGNATURE) { + use_second_page = false; + } +@@ -3846,52 +3840,43 @@ int log_replay(struct ntfs_inode *ni, bool *initialized) + } + + if (use_second_page) { +- kfree(rst_info.r_page); +- memcpy(&rst_info, &rst_info2, sizeof(struct restart_info)); +- rst_info2.r_page = NULL; ++ kfree(log->rst_info.r_page); ++ memcpy(&log->rst_info, &log->rst_info2, ++ sizeof(struct restart_info)); ++ log->rst_info2.r_page = NULL; + } + + use_first_page: +- kfree(rst_info2.r_page); ++ kfree(log->rst_info2.r_page); + + check_restart_area: + /* + * If the restart area is at offset 0, we want + * to write the second restart area first. + */ +- log->init_ra = !!rst_info.vbo; ++ log->init_ra = !!log->rst_info.vbo; + + /* If we have a valid page then grab a pointer to the restart area. */ +- ra2 = rst_info.valid_page ? +- Add2Ptr(rst_info.r_page, +- le16_to_cpu(rst_info.r_page->ra_off)) : ++ ra2 = log->rst_info.valid_page ? ++ Add2Ptr(log->rst_info.r_page, ++ le16_to_cpu(log->rst_info.r_page->ra_off)) : + NULL; + +- if (rst_info.chkdsk_was_run || ++ if (log->rst_info.chkdsk_was_run || + (ra2 && ra2->client_idx[1] == LFS_NO_CLIENT_LE)) { + bool wrapped = false; + bool use_multi_page = false; + u32 open_log_count; + + /* Do some checks based on whether we have a valid log page. */ +- if (!rst_info.valid_page) { +- open_log_count = get_random_u32(); +- goto init_log_instance; +- } +- open_log_count = le32_to_cpu(ra2->open_log_count); +- +- /* +- * If the restart page size isn't changing then we want to +- * check how much work we need to do. +- */ +- if (page_size != le32_to_cpu(rst_info.r_page->sys_page_size)) +- goto init_log_instance; ++ open_log_count = log->rst_info.valid_page ? ++ le32_to_cpu(ra2->open_log_count) : ++ get_random_u32(); + +-init_log_instance: +- log_init_pg_hdr(log, page_size, page_size, 1, 1); ++ log_init_pg_hdr(log, 1, 1); + +- log_create(log, l_size, rst_info.last_lsn, open_log_count, +- wrapped, use_multi_page); ++ log_create(log, log->rst_info.last_lsn, open_log_count, wrapped, ++ use_multi_page); + + ra = log_create_ra(log); + if (!ra) { +@@ -3916,28 +3901,27 @@ int log_replay(struct ntfs_inode *ni, bool *initialized) + * use the log file. We must use the system page size instead of the + * default size if there is not a clean shutdown. + */ +- t32 = le32_to_cpu(rst_info.r_page->sys_page_size); +- if (page_size != t32) { +- l_size = orig_file_size; +- page_size = +- norm_file_page(t32, &l_size, t32 == DefaultLogPageSize); ++ t32 = le32_to_cpu(log->rst_info.r_page->sys_page_size); ++ if (log->page_size != t32) { ++ log->l_size = log->orig_file_size; ++ log->page_size = norm_file_page(t32, &log->l_size, ++ t32 == DefaultLogPageSize); + } + +- if (page_size != t32 || +- page_size != le32_to_cpu(rst_info.r_page->page_size)) { ++ if (log->page_size != t32 || ++ log->page_size != le32_to_cpu(log->rst_info.r_page->page_size)) { + err = -EINVAL; + goto out; + } + + /* If the file size has shrunk then we won't mount it. */ +- if (l_size < le64_to_cpu(ra2->l_size)) { ++ if (log->l_size < le64_to_cpu(ra2->l_size)) { + err = -EINVAL; + goto out; + } + +- log_init_pg_hdr(log, page_size, page_size, +- le16_to_cpu(rst_info.r_page->major_ver), +- le16_to_cpu(rst_info.r_page->minor_ver)); ++ log_init_pg_hdr(log, le16_to_cpu(log->rst_info.r_page->major_ver), ++ le16_to_cpu(log->rst_info.r_page->minor_ver)); + + log->l_size = le64_to_cpu(ra2->l_size); + log->seq_num_bits = le32_to_cpu(ra2->seq_num_bits); +@@ -3945,7 +3929,7 @@ int log_replay(struct ntfs_inode *ni, bool *initialized) + log->seq_num_mask = (8 << log->file_data_bits) - 1; + log->last_lsn = le64_to_cpu(ra2->current_lsn); + log->seq_num = log->last_lsn >> log->file_data_bits; +- log->ra_off = le16_to_cpu(rst_info.r_page->ra_off); ++ log->ra_off = le16_to_cpu(log->rst_info.r_page->ra_off); + log->restart_size = log->sys_page_size - log->ra_off; + log->record_header_len = le16_to_cpu(ra2->rec_hdr_len); + log->ra_size = le16_to_cpu(ra2->ra_len); +@@ -4045,7 +4029,7 @@ int log_replay(struct ntfs_inode *ni, bool *initialized) + log->current_avail = current_log_avail(log); + + /* Remember which restart area to write first. */ +- log->init_ra = rst_info.vbo; ++ log->init_ra = log->rst_info.vbo; + + process_log: + /* 1.0, 1.1, 2.0 log->major_ver/minor_ver - short values. */ +@@ -4105,7 +4089,7 @@ int log_replay(struct ntfs_inode *ni, bool *initialized) + log->client_id.seq_num = cr->seq_num; + log->client_id.client_idx = client; + +- err = read_rst_area(log, &rst, &ra_lsn); ++ err = read_rst_area(log, &rst, &checkpt_lsn); + if (err) + goto out; + +@@ -4114,9 +4098,8 @@ int log_replay(struct ntfs_inode *ni, bool *initialized) + + bytes_per_attr_entry = !rst->major_ver ? 0x2C : 0x28; + +- checkpt_lsn = le64_to_cpu(rst->check_point_start); +- if (!checkpt_lsn) +- checkpt_lsn = ra_lsn; ++ if (rst->check_point_start) ++ checkpt_lsn = le64_to_cpu(rst->check_point_start); + + /* Allocate and Read the Transaction Table. */ + if (!rst->transact_table_len) +@@ -4330,23 +4313,20 @@ int log_replay(struct ntfs_inode *ni, bool *initialized) + lcb = NULL; + + check_attribute_names2: +- if (!rst->attr_names_len) +- goto trace_attribute_table; +- +- ane = attr_names; +- if (!oatbl) +- goto trace_attribute_table; +- while (ane->off) { +- /* TODO: Clear table on exit! */ +- oe = Add2Ptr(oatbl, le16_to_cpu(ane->off)); +- t16 = le16_to_cpu(ane->name_bytes); +- oe->name_len = t16 / sizeof(short); +- oe->ptr = ane->name; +- oe->is_attr_name = 2; +- ane = Add2Ptr(ane, sizeof(struct ATTR_NAME_ENTRY) + t16); +- } +- +-trace_attribute_table: ++ if (rst->attr_names_len && oatbl) { ++ struct ATTR_NAME_ENTRY *ane = attr_names; ++ while (ane->off) { ++ /* TODO: Clear table on exit! */ ++ oe = Add2Ptr(oatbl, le16_to_cpu(ane->off)); ++ t16 = le16_to_cpu(ane->name_bytes); ++ oe->name_len = t16 / sizeof(short); ++ oe->ptr = ane->name; ++ oe->is_attr_name = 2; ++ ane = Add2Ptr(ane, ++ sizeof(struct ATTR_NAME_ENTRY) + t16); ++ } ++ } ++ + /* + * If the checkpt_lsn is zero, then this is a freshly + * formatted disk and we have no work to do. +@@ -5189,7 +5169,7 @@ int log_replay(struct ntfs_inode *ni, bool *initialized) + kfree(oatbl); + kfree(dptbl); + kfree(attr_names); +- kfree(rst_info.r_page); ++ kfree(log->rst_info.r_page); + + kfree(ra); + kfree(log->one_page_buf); +diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c +index fbfe21dbb4259..ae2ef5c11868c 100644 +--- a/fs/ntfs3/fsntfs.c ++++ b/fs/ntfs3/fsntfs.c +@@ -853,7 +853,8 @@ void ntfs_update_mftmirr(struct ntfs_sb_info *sbi, int wait) + /* + * sb can be NULL here. In this case sbi->flags should be 0 too. + */ +- if (!sb || !(sbi->flags & NTFS_FLAGS_MFTMIRR)) ++ if (!sb || !(sbi->flags & NTFS_FLAGS_MFTMIRR) || ++ unlikely(ntfs3_forced_shutdown(sb))) + return; + + blocksize = sb->s_blocksize; +@@ -1006,6 +1007,30 @@ static inline __le32 security_hash(const void *sd, size_t bytes) + return cpu_to_le32(hash); + } + ++/* ++ * simple wrapper for sb_bread_unmovable. ++ */ ++struct buffer_head *ntfs_bread(struct super_block *sb, sector_t block) ++{ ++ struct ntfs_sb_info *sbi = sb->s_fs_info; ++ struct buffer_head *bh; ++ ++ if (unlikely(block >= sbi->volume.blocks)) { ++ /* prevent generic message "attempt to access beyond end of device" */ ++ ntfs_err(sb, "try to read out of volume at offset 0x%llx", ++ (u64)block << sb->s_blocksize_bits); ++ return NULL; ++ } ++ ++ bh = sb_bread_unmovable(sb, block); ++ if (bh) ++ return bh; ++ ++ ntfs_err(sb, "failed to read volume at offset 0x%llx", ++ (u64)block << sb->s_blocksize_bits); ++ return NULL; ++} ++ + int ntfs_sb_read(struct super_block *sb, u64 lbo, size_t bytes, void *buffer) + { + struct block_device *bdev = sb->s_bdev; +@@ -2128,8 +2153,8 @@ int ntfs_insert_security(struct ntfs_sb_info *sbi, + if (le32_to_cpu(d_security->size) == new_sec_size && + d_security->key.hash == hash_key.hash && + !memcmp(d_security + 1, sd, size_sd)) { +- *security_id = d_security->key.sec_id; + /* Such security already exists. */ ++ *security_id = d_security->key.sec_id; + err = 0; + goto out; + } +diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c +index cf92b2433f7a7..daabaad63aaf6 100644 +--- a/fs/ntfs3/index.c ++++ b/fs/ntfs3/index.c +@@ -1462,7 +1462,7 @@ static int indx_create_allocate(struct ntfs_index *indx, struct ntfs_inode *ni, + goto out2; + + if (in->name == I30_NAME) { +- ni->vfs_inode.i_size = data_size; ++ i_size_write(&ni->vfs_inode, data_size); + inode_set_bytes(&ni->vfs_inode, alloc_size); + } + +@@ -1544,7 +1544,7 @@ static int indx_add_allocate(struct ntfs_index *indx, struct ntfs_inode *ni, + } + + if (in->name == I30_NAME) +- ni->vfs_inode.i_size = data_size; ++ i_size_write(&ni->vfs_inode, data_size); + + *vbn = bit << indx->idx2vbn_bits; + +@@ -2090,7 +2090,7 @@ static int indx_shrink(struct ntfs_index *indx, struct ntfs_inode *ni, + return err; + + if (in->name == I30_NAME) +- ni->vfs_inode.i_size = new_data; ++ i_size_write(&ni->vfs_inode, new_data); + + bpb = bitmap_size(bit); + if (bpb * 8 == nbits) +@@ -2576,7 +2576,7 @@ int indx_delete_entry(struct ntfs_index *indx, struct ntfs_inode *ni, + err = attr_set_size(ni, ATTR_ALLOC, in->name, in->name_len, + &indx->alloc_run, 0, NULL, false, NULL); + if (in->name == I30_NAME) +- ni->vfs_inode.i_size = 0; ++ i_size_write(&ni->vfs_inode, 0); + + err = ni_remove_attr(ni, ATTR_ALLOC, in->name, in->name_len, + false, NULL); +diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c +index 5e3d713749185..eb7a8c9fba018 100644 +--- a/fs/ntfs3/inode.c ++++ b/fs/ntfs3/inode.c +@@ -345,9 +345,7 @@ static struct inode *ntfs_read_mft(struct inode *inode, + inode->i_size = le16_to_cpu(rp.SymbolicLinkReparseBuffer + .PrintNameLength) / + sizeof(u16); +- + ni->i_valid = inode->i_size; +- + /* Clear directory bit. */ + if (ni->ni_flags & NI_FLAG_DIR) { + indx_clear(&ni->dir); +@@ -412,7 +410,6 @@ static struct inode *ntfs_read_mft(struct inode *inode, + goto out; + + if (!is_match && name) { +- /* Reuse rec as buffer for ascii name. */ + err = -ENOENT; + goto out; + } +@@ -427,6 +424,7 @@ static struct inode *ntfs_read_mft(struct inode *inode, + + if (names != le16_to_cpu(rec->hard_links)) { + /* Correct minor error on the fly. Do not mark inode as dirty. */ ++ ntfs_inode_warn(inode, "Correct links count -> %u.", names); + rec->hard_links = cpu_to_le16(names); + ni->mi.dirty = true; + } +@@ -653,9 +651,10 @@ static noinline int ntfs_get_block_vbo(struct inode *inode, u64 vbo, + off = vbo & (PAGE_SIZE - 1); + folio_set_bh(bh, folio, off); + +- err = bh_read(bh, 0); +- if (err < 0) ++ if (bh_read(bh, 0) < 0) { ++ err = -EIO; + goto out; ++ } + folio_zero_segment(folio, off + voff, off + block_size); + } + } +@@ -853,9 +852,13 @@ static int ntfs_resident_writepage(struct folio *folio, + struct writeback_control *wbc, void *data) + { + struct address_space *mapping = data; +- struct ntfs_inode *ni = ntfs_i(mapping->host); ++ struct inode *inode = mapping->host; ++ struct ntfs_inode *ni = ntfs_i(inode); + int ret; + ++ if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) ++ return -EIO; ++ + ni_lock(ni); + ret = attr_data_write_resident(ni, &folio->page); + ni_unlock(ni); +@@ -869,7 +872,12 @@ static int ntfs_resident_writepage(struct folio *folio, + static int ntfs_writepages(struct address_space *mapping, + struct writeback_control *wbc) + { +- if (is_resident(ntfs_i(mapping->host))) ++ struct inode *inode = mapping->host; ++ ++ if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) ++ return -EIO; ++ ++ if (is_resident(ntfs_i(inode))) + return write_cache_pages(mapping, wbc, ntfs_resident_writepage, + mapping); + return mpage_writepages(mapping, wbc, ntfs_get_block); +@@ -889,6 +897,9 @@ int ntfs_write_begin(struct file *file, struct address_space *mapping, + struct inode *inode = mapping->host; + struct ntfs_inode *ni = ntfs_i(inode); + ++ if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) ++ return -EIO; ++ + *pagep = NULL; + if (is_resident(ni)) { + struct page *page = +@@ -974,7 +985,7 @@ int ntfs_write_end(struct file *file, struct address_space *mapping, loff_t pos, + } + + if (pos + err > inode->i_size) { +- inode->i_size = pos + err; ++ i_size_write(inode, pos + err); + dirty = true; + } + +@@ -1306,6 +1317,11 @@ struct inode *ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir, + goto out1; + } + ++ if (unlikely(ntfs3_forced_shutdown(sb))) { ++ err = -EIO; ++ goto out2; ++ } ++ + /* Mark rw ntfs as dirty. it will be cleared at umount. */ + ntfs_set_state(sbi, NTFS_DIRTY_DIRTY); + +diff --git a/fs/ntfs3/namei.c b/fs/ntfs3/namei.c +index ee3093be51701..cae41db0aaa7d 100644 +--- a/fs/ntfs3/namei.c ++++ b/fs/ntfs3/namei.c +@@ -181,6 +181,9 @@ static int ntfs_unlink(struct inode *dir, struct dentry *dentry) + struct ntfs_inode *ni = ntfs_i(dir); + int err; + ++ if (unlikely(ntfs3_forced_shutdown(dir->i_sb))) ++ return -EIO; ++ + ni_lock_dir(ni); + + err = ntfs_unlink_inode(dir, dentry); +@@ -199,6 +202,9 @@ static int ntfs_symlink(struct mnt_idmap *idmap, struct inode *dir, + u32 size = strlen(symname); + struct inode *inode; + ++ if (unlikely(ntfs3_forced_shutdown(dir->i_sb))) ++ return -EIO; ++ + inode = ntfs_create_inode(idmap, dir, dentry, NULL, S_IFLNK | 0777, 0, + symname, size, NULL); + +@@ -227,6 +233,9 @@ static int ntfs_rmdir(struct inode *dir, struct dentry *dentry) + struct ntfs_inode *ni = ntfs_i(dir); + int err; + ++ if (unlikely(ntfs3_forced_shutdown(dir->i_sb))) ++ return -EIO; ++ + ni_lock_dir(ni); + + err = ntfs_unlink_inode(dir, dentry); +@@ -264,6 +273,9 @@ static int ntfs_rename(struct mnt_idmap *idmap, struct inode *dir, + 1024); + static_assert(PATH_MAX >= 4 * 1024); + ++ if (unlikely(ntfs3_forced_shutdown(sb))) ++ return -EIO; ++ + if (flags & ~RENAME_NOREPLACE) + return -EINVAL; + +diff --git a/fs/ntfs3/ntfs.h b/fs/ntfs3/ntfs.h +index 86aecbb01a92f..9c7478150a035 100644 +--- a/fs/ntfs3/ntfs.h ++++ b/fs/ntfs3/ntfs.h +@@ -523,12 +523,10 @@ struct ATTR_LIST_ENTRY { + __le64 vcn; // 0x08: Starting VCN of this attribute. + struct MFT_REF ref; // 0x10: MFT record number with attribute. + __le16 id; // 0x18: struct ATTRIB ID. +- __le16 name[3]; // 0x1A: Just to align. To get real name can use bNameOffset. ++ __le16 name[]; // 0x1A: To get real name use name_off. + + }; // sizeof(0x20) + +-static_assert(sizeof(struct ATTR_LIST_ENTRY) == 0x20); +- + static inline u32 le_size(u8 name_len) + { + return ALIGN(offsetof(struct ATTR_LIST_ENTRY, name) + +diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h +index a46d30b84bf39..627419bd6f778 100644 +--- a/fs/ntfs3/ntfs_fs.h ++++ b/fs/ntfs3/ntfs_fs.h +@@ -61,6 +61,8 @@ enum utf16_endian; + + /* sbi->flags */ + #define NTFS_FLAGS_NODISCARD 0x00000001 ++/* ntfs in shutdown state. */ ++#define NTFS_FLAGS_SHUTDOWN_BIT 0x00000002 /* == 4*/ + /* Set when LogFile is replaying. */ + #define NTFS_FLAGS_LOG_REPLAYING 0x00000008 + /* Set when we changed first MFT's which copy must be updated in $MftMirr. */ +@@ -226,7 +228,7 @@ struct ntfs_sb_info { + u64 maxbytes; // Maximum size for normal files. + u64 maxbytes_sparse; // Maximum size for sparse file. + +- u32 flags; // See NTFS_FLAGS_XXX. ++ unsigned long flags; // See NTFS_FLAGS_ + + CLST zone_max; // Maximum MFT zone length in clusters + CLST bad_clusters; // The count of marked bad clusters. +@@ -584,6 +586,7 @@ bool check_index_header(const struct INDEX_HDR *hdr, size_t bytes); + int log_replay(struct ntfs_inode *ni, bool *initialized); + + /* Globals from fsntfs.c */ ++struct buffer_head *ntfs_bread(struct super_block *sb, sector_t block); + bool ntfs_fix_pre_write(struct NTFS_RECORD_HEADER *rhdr, size_t bytes); + int ntfs_fix_post_read(struct NTFS_RECORD_HEADER *rhdr, size_t bytes, + bool simple); +@@ -872,7 +875,7 @@ int ntfs_init_acl(struct mnt_idmap *idmap, struct inode *inode, + + int ntfs_acl_chmod(struct mnt_idmap *idmap, struct dentry *dentry); + ssize_t ntfs_listxattr(struct dentry *dentry, char *buffer, size_t size); +-extern const struct xattr_handler * const ntfs_xattr_handlers[]; ++extern const struct xattr_handler *const ntfs_xattr_handlers[]; + + int ntfs_save_wsl_perm(struct inode *inode, __le16 *ea_size); + void ntfs_get_wsl_perm(struct inode *inode); +@@ -999,6 +1002,11 @@ static inline struct ntfs_sb_info *ntfs_sb(struct super_block *sb) + return sb->s_fs_info; + } + ++static inline int ntfs3_forced_shutdown(struct super_block *sb) ++{ ++ return test_bit(NTFS_FLAGS_SHUTDOWN_BIT, &ntfs_sb(sb)->flags); ++} ++ + /* + * ntfs_up_cluster - Align up on cluster boundary. + */ +@@ -1025,19 +1033,6 @@ static inline u64 bytes_to_block(const struct super_block *sb, u64 size) + return (size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; + } + +-static inline struct buffer_head *ntfs_bread(struct super_block *sb, +- sector_t block) +-{ +- struct buffer_head *bh = sb_bread(sb, block); +- +- if (bh) +- return bh; +- +- ntfs_err(sb, "failed to read volume at offset 0x%llx", +- (u64)block << sb->s_blocksize_bits); +- return NULL; +-} +- + static inline struct ntfs_inode *ntfs_i(struct inode *inode) + { + return container_of(inode, struct ntfs_inode, vfs_inode); +diff --git a/fs/ntfs3/record.c b/fs/ntfs3/record.c +index 53629b1f65e99..6aa3a9d44df1b 100644 +--- a/fs/ntfs3/record.c ++++ b/fs/ntfs3/record.c +@@ -279,7 +279,7 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr) + if (t16 > asize) + return NULL; + +- if (t16 + le32_to_cpu(attr->res.data_size) > asize) ++ if (le32_to_cpu(attr->res.data_size) > asize - t16) + return NULL; + + t32 = sizeof(short) * attr->name_len; +@@ -535,8 +535,20 @@ bool mi_remove_attr(struct ntfs_inode *ni, struct mft_inode *mi, + return false; + + if (ni && is_attr_indexed(attr)) { +- le16_add_cpu(&ni->mi.mrec->hard_links, -1); +- ni->mi.dirty = true; ++ u16 links = le16_to_cpu(ni->mi.mrec->hard_links); ++ struct ATTR_FILE_NAME *fname = ++ attr->type != ATTR_NAME ? ++ NULL : ++ resident_data_ex(attr, ++ SIZEOF_ATTRIBUTE_FILENAME); ++ if (fname && fname->type == FILE_NAME_DOS) { ++ /* Do not decrease links count deleting DOS name. */ ++ } else if (!links) { ++ /* minor error. Not critical. */ ++ } else { ++ ni->mi.mrec->hard_links = cpu_to_le16(links - 1); ++ ni->mi.dirty = true; ++ } + } + + used -= asize; +diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c +index 9153dffde950c..c55a29793a8d8 100644 +--- a/fs/ntfs3/super.c ++++ b/fs/ntfs3/super.c +@@ -625,7 +625,7 @@ static void ntfs3_free_sbi(struct ntfs_sb_info *sbi) + { + kfree(sbi->new_rec); + kvfree(ntfs_put_shared(sbi->upcase)); +- kfree(sbi->def_table); ++ kvfree(sbi->def_table); + kfree(sbi->compress.lznt); + #ifdef CONFIG_NTFS3_LZX_XPRESS + xpress_free_decompressor(sbi->compress.xpress); +@@ -714,6 +714,14 @@ static int ntfs_show_options(struct seq_file *m, struct dentry *root) + return 0; + } + ++/* ++ * ntfs_shutdown - super_operations::shutdown ++ */ ++static void ntfs_shutdown(struct super_block *sb) ++{ ++ set_bit(NTFS_FLAGS_SHUTDOWN_BIT, &ntfs_sb(sb)->flags); ++} ++ + /* + * ntfs_sync_fs - super_operations::sync_fs + */ +@@ -724,6 +732,9 @@ static int ntfs_sync_fs(struct super_block *sb, int wait) + struct ntfs_inode *ni; + struct inode *inode; + ++ if (unlikely(ntfs3_forced_shutdown(sb))) ++ return -EIO; ++ + ni = sbi->security.ni; + if (ni) { + inode = &ni->vfs_inode; +@@ -763,6 +774,7 @@ static const struct super_operations ntfs_sops = { + .put_super = ntfs_put_super, + .statfs = ntfs_statfs, + .show_options = ntfs_show_options, ++ .shutdown = ntfs_shutdown, + .sync_fs = ntfs_sync_fs, + .write_inode = ntfs3_write_inode, + }; +@@ -866,6 +878,7 @@ static int ntfs_init_from_boot(struct super_block *sb, u32 sector_size, + u16 fn, ao; + u8 cluster_bits; + u32 boot_off = 0; ++ sector_t boot_block = 0; + const char *hint = "Primary boot"; + + /* Save original dev_size. Used with alternative boot. */ +@@ -873,11 +886,11 @@ static int ntfs_init_from_boot(struct super_block *sb, u32 sector_size, + + sbi->volume.blocks = dev_size >> PAGE_SHIFT; + +- bh = ntfs_bread(sb, 0); ++read_boot: ++ bh = ntfs_bread(sb, boot_block); + if (!bh) +- return -EIO; ++ return boot_block ? -EINVAL : -EIO; + +-check_boot: + err = -EINVAL; + + /* Corrupted image; do not read OOB */ +@@ -1108,26 +1121,24 @@ static int ntfs_init_from_boot(struct super_block *sb, u32 sector_size, + } + + out: +- if (err == -EINVAL && !bh->b_blocknr && dev_size0 > PAGE_SHIFT) { ++ brelse(bh); ++ ++ if (err == -EINVAL && !boot_block && dev_size0 > PAGE_SHIFT) { + u32 block_size = min_t(u32, sector_size, PAGE_SIZE); + u64 lbo = dev_size0 - sizeof(*boot); + +- /* +- * Try alternative boot (last sector) +- */ +- brelse(bh); +- +- sb_set_blocksize(sb, block_size); +- bh = ntfs_bread(sb, lbo >> blksize_bits(block_size)); +- if (!bh) +- return -EINVAL; +- ++ boot_block = lbo >> blksize_bits(block_size); + boot_off = lbo & (block_size - 1); +- hint = "Alternative boot"; +- dev_size = dev_size0; /* restore original size. */ +- goto check_boot; ++ if (boot_block && block_size >= boot_off + sizeof(*boot)) { ++ /* ++ * Try alternative boot (last sector) ++ */ ++ sb_set_blocksize(sb, block_size); ++ hint = "Alternative boot"; ++ dev_size = dev_size0; /* restore original size. */ ++ goto read_boot; ++ } + } +- brelse(bh); + + return err; + } +diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c +index 4274b6f31cfa1..53e7d1fa036aa 100644 +--- a/fs/ntfs3/xattr.c ++++ b/fs/ntfs3/xattr.c +@@ -219,6 +219,9 @@ static ssize_t ntfs_list_ea(struct ntfs_inode *ni, char *buffer, + if (!ea->name_len) + break; + ++ if (ea->name_len > ea_size) ++ break; ++ + if (buffer) { + /* Check if we can use field ea->name */ + if (off + ea_size > size) +@@ -744,6 +747,9 @@ static int ntfs_getxattr(const struct xattr_handler *handler, struct dentry *de, + int err; + struct ntfs_inode *ni = ntfs_i(inode); + ++ if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) ++ return -EIO; ++ + /* Dispatch request. */ + if (!strcmp(name, SYSTEM_DOS_ATTRIB)) { + /* system.dos_attrib */ +diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c +index d64a306a414be..5730c65ffb40d 100644 +--- a/fs/smb/client/cached_dir.c ++++ b/fs/smb/client/cached_dir.c +@@ -151,7 +151,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon, + return -EOPNOTSUPP; + + ses = tcon->ses; +- server = ses->server; ++ server = cifs_pick_channel(ses); + cfids = tcon->cfids; + + if (!server->ops->new_lease_key) +@@ -367,6 +367,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon, + atomic_inc(&tcon->num_remote_opens); + } + kfree(utf16_path); ++ + return rc; + } + +diff --git a/fs/smb/client/cifsencrypt.c b/fs/smb/client/cifsencrypt.c +index ef4c2e3c9fa61..6322f0f68a176 100644 +--- a/fs/smb/client/cifsencrypt.c ++++ b/fs/smb/client/cifsencrypt.c +@@ -572,7 +572,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, + len = cifs_strtoUTF16(user, ses->user_name, len, nls_cp); + UniStrupr(user); + } else { +- memset(user, '\0', 2); ++ *(u16 *)user = 0; + } + + rc = crypto_shash_update(ses->server->secmech.hmacmd5, +diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h +index 942e6ece56b1a..462554917e5a1 100644 +--- a/fs/smb/client/cifsglob.h ++++ b/fs/smb/client/cifsglob.h +@@ -82,7 +82,7 @@ + #define SMB_INTERFACE_POLL_INTERVAL 600 + + /* maximum number of PDUs in one compound */ +-#define MAX_COMPOUND 5 ++#define MAX_COMPOUND 7 + + /* + * Default number of credits to keep available for SMB3. +@@ -1018,6 +1018,8 @@ struct cifs_chan { + __u8 signkey[SMB3_SIGN_KEY_SIZE]; + }; + ++#define CIFS_SES_FLAG_SCALE_CHANNELS (0x1) ++ + /* + * Session structure. One of these for each uid session with a particular host + */ +@@ -1050,6 +1052,7 @@ struct cifs_ses { + enum securityEnum sectype; /* what security flavor was specified? */ + bool sign; /* is signing required? */ + bool domainAuto:1; ++ unsigned int flags; + __u16 session_flags; + __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE]; + __u8 smb3encryptionkey[SMB3_ENC_DEC_KEY_SIZE]; +@@ -1820,6 +1823,13 @@ static inline bool is_retryable_error(int error) + return false; + } + ++static inline bool is_replayable_error(int error) ++{ ++ if (error == -EAGAIN || error == -ECONNABORTED) ++ return true; ++ return false; ++} ++ + + /* cifs_get_writable_file() flags */ + #define FIND_WR_ANY 0 +diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c +index ea1da3ce0d401..c3d805ecb7f11 100644 +--- a/fs/smb/client/connect.c ++++ b/fs/smb/client/connect.c +@@ -233,6 +233,12 @@ cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server, + list_for_each_entry_safe(ses, nses, &pserver->smb_ses_list, smb_ses_list) { + /* check if iface is still active */ + spin_lock(&ses->chan_lock); ++ if (cifs_ses_get_chan_index(ses, server) == ++ CIFS_INVAL_CHAN_INDEX) { ++ spin_unlock(&ses->chan_lock); ++ continue; ++ } ++ + if (!cifs_chan_is_iface_active(ses, server)) { + spin_unlock(&ses->chan_lock); + cifs_chan_update_iface(ses, server); +@@ -4225,6 +4231,11 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru + + /* only send once per connect */ + spin_lock(&tcon->tc_lock); ++ ++ /* if tcon is marked for needing reconnect, update state */ ++ if (tcon->need_reconnect) ++ tcon->status = TID_NEED_TCON; ++ + if (tcon->status == TID_GOOD) { + spin_unlock(&tcon->tc_lock); + return 0; +diff --git a/fs/smb/client/dfs.c b/fs/smb/client/dfs.c +index a8a1d386da656..449c59830039b 100644 +--- a/fs/smb/client/dfs.c ++++ b/fs/smb/client/dfs.c +@@ -565,6 +565,11 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru + + /* only send once per connect */ + spin_lock(&tcon->tc_lock); ++ ++ /* if tcon is marked for needing reconnect, update state */ ++ if (tcon->need_reconnect) ++ tcon->status = TID_NEED_TCON; ++ + if (tcon->status == TID_GOOD) { + spin_unlock(&tcon->tc_lock); + return 0; +@@ -625,8 +630,8 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru + spin_lock(&tcon->tc_lock); + if (tcon->status == TID_IN_TCON) + tcon->status = TID_GOOD; +- spin_unlock(&tcon->tc_lock); + tcon->need_reconnect = false; ++ spin_unlock(&tcon->tc_lock); + } + + return rc; +diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c +index 32a8525415d96..4cbb5487bd8d0 100644 +--- a/fs/smb/client/file.c ++++ b/fs/smb/client/file.c +@@ -175,6 +175,9 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon) + + /* only send once per connect */ + spin_lock(&tcon->tc_lock); ++ if (tcon->need_reconnect) ++ tcon->status = TID_NEED_RECON; ++ + if (tcon->status != TID_NEED_RECON) { + spin_unlock(&tcon->tc_lock); + return; +diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c +index 75f2c8734ff56..6ecbf48d0f0c6 100644 +--- a/fs/smb/client/fs_context.c ++++ b/fs/smb/client/fs_context.c +@@ -210,7 +210,7 @@ cifs_parse_security_flavors(struct fs_context *fc, char *value, struct smb3_fs_c + + switch (match_token(value, cifs_secflavor_tokens, args)) { + case Opt_sec_krb5p: +- cifs_errorf(fc, "sec=krb5p is not supported!\n"); ++ cifs_errorf(fc, "sec=krb5p is not supported. Use sec=krb5,seal instead\n"); + return 1; + case Opt_sec_krb5i: + ctx->sign = true; +diff --git a/fs/smb/client/readdir.c b/fs/smb/client/readdir.c +index d30ea2005eb36..e23cd216bffbe 100644 +--- a/fs/smb/client/readdir.c ++++ b/fs/smb/client/readdir.c +@@ -299,14 +299,16 @@ cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info, + } + + static void cifs_fulldir_info_to_fattr(struct cifs_fattr *fattr, +- SEARCH_ID_FULL_DIR_INFO *info, ++ const void *info, + struct cifs_sb_info *cifs_sb) + { ++ const FILE_FULL_DIRECTORY_INFO *di = info; ++ + __dir_info_to_fattr(fattr, info); + +- /* See MS-FSCC 2.4.19 FileIdFullDirectoryInformation */ ++ /* See MS-FSCC 2.4.14, 2.4.19 */ + if (fattr->cf_cifsattrs & ATTR_REPARSE) +- fattr->cf_cifstag = le32_to_cpu(info->EaSize); ++ fattr->cf_cifstag = le32_to_cpu(di->EaSize); + cifs_fill_common_info(fattr, cifs_sb); + } + +@@ -420,7 +422,7 @@ _initiate_cifs_search(const unsigned int xid, struct file *file, + } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { + cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO; + } else /* not srvinos - BB fixme add check for backlevel? */ { +- cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO; ++ cifsFile->srch_inf.info_level = SMB_FIND_FILE_FULL_DIRECTORY_INFO; + } + + search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME; +@@ -1014,10 +1016,9 @@ static int cifs_filldir(char *find_entry, struct file *file, + (FIND_FILE_STANDARD_INFO *)find_entry, + cifs_sb); + break; ++ case SMB_FIND_FILE_FULL_DIRECTORY_INFO: + case SMB_FIND_FILE_ID_FULL_DIR_INFO: +- cifs_fulldir_info_to_fattr(&fattr, +- (SEARCH_ID_FULL_DIR_INFO *)find_entry, +- cifs_sb); ++ cifs_fulldir_info_to_fattr(&fattr, find_entry, cifs_sb); + break; + default: + cifs_dir_info_to_fattr(&fattr, +diff --git a/fs/smb/client/sess.c b/fs/smb/client/sess.c +index a1b9734564711..94c5d50aa3474 100644 +--- a/fs/smb/client/sess.c ++++ b/fs/smb/client/sess.c +@@ -75,6 +75,10 @@ cifs_ses_get_chan_index(struct cifs_ses *ses, + { + unsigned int i; + ++ /* if the channel is waiting for termination */ ++ if (server && server->terminate) ++ return CIFS_INVAL_CHAN_INDEX; ++ + for (i = 0; i < ses->chan_count; i++) { + if (ses->chans[i].server == server) + return i; +@@ -84,7 +88,6 @@ cifs_ses_get_chan_index(struct cifs_ses *ses, + if (server) + cifs_dbg(VFS, "unable to get chan index for server: 0x%llx", + server->conn_id); +- WARN_ON(1); + return CIFS_INVAL_CHAN_INDEX; + } + +diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c +index 5d9c87d2e1e01..9d34a55fdb5e4 100644 +--- a/fs/smb/client/smb2pdu.c ++++ b/fs/smb/client/smb2pdu.c +@@ -178,6 +178,7 @@ cifs_chan_skip_or_disable(struct cifs_ses *ses, + } + + ses->chans[chan_index].server = NULL; ++ server->terminate = true; + spin_unlock(&ses->chan_lock); + + /* +@@ -188,7 +189,6 @@ cifs_chan_skip_or_disable(struct cifs_ses *ses, + */ + cifs_put_tcp_session(server, from_reconnect); + +- server->terminate = true; + cifs_signal_cifsd_for_reconnect(server, false); + + /* mark primary server as needing reconnect */ +@@ -399,6 +399,15 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon, + goto out; + } + ++ spin_lock(&ses->ses_lock); ++ if (ses->flags & CIFS_SES_FLAG_SCALE_CHANNELS) { ++ spin_unlock(&ses->ses_lock); ++ mutex_unlock(&ses->session_mutex); ++ goto skip_add_channels; ++ } ++ ses->flags |= CIFS_SES_FLAG_SCALE_CHANNELS; ++ spin_unlock(&ses->ses_lock); ++ + if (!rc && + (server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) { + mutex_unlock(&ses->session_mutex); +@@ -428,15 +437,22 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon, + if (ses->chan_max > ses->chan_count && + ses->iface_count && + !SERVER_IS_CHAN(server)) { +- if (ses->chan_count == 1) ++ if (ses->chan_count == 1) { + cifs_server_dbg(VFS, "supports multichannel now\n"); ++ queue_delayed_work(cifsiod_wq, &tcon->query_interfaces, ++ (SMB_INTERFACE_POLL_INTERVAL * HZ)); ++ } + + cifs_try_adding_channels(ses); + } + } else { + mutex_unlock(&ses->session_mutex); + } ++ + skip_add_channels: ++ spin_lock(&ses->ses_lock); ++ ses->flags &= ~CIFS_SES_FLAG_SCALE_CHANNELS; ++ spin_unlock(&ses->ses_lock); + + if (smb2_command != SMB2_INTERNAL_CMD) + mod_delayed_work(cifsiod_wq, &server->reconnect, 0); +@@ -5076,6 +5092,9 @@ int SMB2_query_directory_init(const unsigned int xid, + case SMB_FIND_FILE_POSIX_INFO: + req->FileInformationClass = SMB_FIND_FILE_POSIX_INFO; + break; ++ case SMB_FIND_FILE_FULL_DIRECTORY_INFO: ++ req->FileInformationClass = FILE_FULL_DIRECTORY_INFORMATION; ++ break; + default: + cifs_tcon_dbg(VFS, "info level %u isn't supported\n", + info_level); +@@ -5145,6 +5164,9 @@ smb2_parse_query_directory(struct cifs_tcon *tcon, + /* note that posix payload are variable size */ + info_buf_size = sizeof(struct smb2_posix_info); + break; ++ case SMB_FIND_FILE_FULL_DIRECTORY_INFO: ++ info_buf_size = sizeof(FILE_FULL_DIRECTORY_INFO); ++ break; + default: + cifs_tcon_dbg(VFS, "info level %u isn't supported\n", + srch_inf->info_level); +diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c +index 4f717ad7c21b4..994d701934329 100644 +--- a/fs/smb/client/transport.c ++++ b/fs/smb/client/transport.c +@@ -400,10 +400,17 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, + server->conn_id, server->hostname); + } + smbd_done: +- if (rc < 0 && rc != -EINTR) ++ /* ++ * there's hardly any use for the layers above to know the ++ * actual error code here. All they should do at this point is ++ * to retry the connection and hope it goes away. ++ */ ++ if (rc < 0 && rc != -EINTR && rc != -EAGAIN) { + cifs_server_dbg(VFS, "Error %d sending data on socket to server\n", + rc); +- else if (rc > 0) ++ rc = -ECONNABORTED; ++ cifs_signal_cifsd_for_reconnect(server, false); ++ } else if (rc > 0) + rc = 0; + out: + cifs_in_send_dec(server); +@@ -428,8 +435,8 @@ smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, + if (!(flags & CIFS_TRANSFORM_REQ)) + return __smb_send_rqst(server, num_rqst, rqst); + +- if (num_rqst > MAX_COMPOUND - 1) +- return -ENOMEM; ++ if (WARN_ON_ONCE(num_rqst > MAX_COMPOUND - 1)) ++ return -EIO; + + if (!server->ops->init_transform_rq) { + cifs_server_dbg(VFS, "Encryption requested but transform callback is missing\n"); +@@ -1026,6 +1033,9 @@ struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses) + if (!server || server->terminate) + continue; + ++ if (CIFS_CHAN_NEEDS_RECONNECT(ses, i)) ++ continue; ++ + /* + * strictly speaking, we should pick up req_lock to read + * server->in_flight. But it shouldn't matter much here if we +diff --git a/include/kunit/resource.h b/include/kunit/resource.h +index c7383e90f5c9e..4ad69a2642a51 100644 +--- a/include/kunit/resource.h ++++ b/include/kunit/resource.h +@@ -390,6 +390,27 @@ void kunit_remove_resource(struct kunit *test, struct kunit_resource *res); + /* A 'deferred action' function to be used with kunit_add_action. */ + typedef void (kunit_action_t)(void *); + ++/** ++ * KUNIT_DEFINE_ACTION_WRAPPER() - Wrap a function for use as a deferred action. ++ * ++ * @wrapper: The name of the new wrapper function define. ++ * @orig: The original function to wrap. ++ * @arg_type: The type of the argument accepted by @orig. ++ * ++ * Defines a wrapper for a function which accepts a single, pointer-sized ++ * argument. This wrapper can then be passed to kunit_add_action() and ++ * similar. This should be used in preference to casting a function ++ * directly to kunit_action_t, as casting function pointers will break ++ * control flow integrity (CFI), leading to crashes. ++ */ ++#define KUNIT_DEFINE_ACTION_WRAPPER(wrapper, orig, arg_type) \ ++ static void wrapper(void *in) \ ++ { \ ++ arg_type arg = (arg_type)in; \ ++ orig(arg); \ ++ } ++ ++ + /** + * kunit_add_action() - Call a function when the test ends. + * @test: Test case to associate the action with. +diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h +index b8610e9d2471f..5edf9fffa0973 100644 +--- a/include/linux/ceph/osd_client.h ++++ b/include/linux/ceph/osd_client.h +@@ -45,6 +45,7 @@ enum ceph_sparse_read_state { + CEPH_SPARSE_READ_HDR = 0, + CEPH_SPARSE_READ_EXTENTS, + CEPH_SPARSE_READ_DATA_LEN, ++ CEPH_SPARSE_READ_DATA_PRE, + CEPH_SPARSE_READ_DATA, + }; + +@@ -64,7 +65,7 @@ struct ceph_sparse_read { + u64 sr_req_len; /* orig request length */ + u64 sr_pos; /* current pos in buffer */ + int sr_index; /* current extent index */ +- __le32 sr_datalen; /* length of actual data */ ++ u32 sr_datalen; /* length of actual data */ + u32 sr_count; /* extent count in reply */ + int sr_ext_len; /* length of extent array */ + struct ceph_sparse_extent *sr_extent; /* extent array */ +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 98b7a7a8c42e3..7f659c26794b5 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -352,6 +352,8 @@ enum rw_hint { + * unrelated IO (like cache flushing, new IO generation, etc). + */ + #define IOCB_DIO_CALLER_COMP (1 << 22) ++/* kiocb is a read or write operation submitted by fs/aio.c. */ ++#define IOCB_AIO_RW (1 << 23) + + /* for use in trace events */ + #define TRACE_IOCB_STRINGS \ +diff --git a/include/linux/iommu.h b/include/linux/iommu.h +index 6291aa7b079b0..81553770e411a 100644 +--- a/include/linux/iommu.h ++++ b/include/linux/iommu.h +@@ -1346,6 +1346,12 @@ static inline bool mm_valid_pasid(struct mm_struct *mm) + { + return mm->pasid != IOMMU_PASID_INVALID; + } ++ ++static inline u32 mm_get_enqcmd_pasid(struct mm_struct *mm) ++{ ++ return mm->pasid; ++} ++ + void mm_pasid_drop(struct mm_struct *mm); + struct iommu_sva *iommu_sva_bind_device(struct device *dev, + struct mm_struct *mm); +@@ -1368,6 +1374,12 @@ static inline u32 iommu_sva_get_pasid(struct iommu_sva *handle) + } + static inline void mm_pasid_init(struct mm_struct *mm) {} + static inline bool mm_valid_pasid(struct mm_struct *mm) { return false; } ++ ++static inline u32 mm_get_enqcmd_pasid(struct mm_struct *mm) ++{ ++ return IOMMU_PASID_INVALID; ++} ++ + static inline void mm_pasid_drop(struct mm_struct *mm) {} + #endif /* CONFIG_IOMMU_SVA */ + +diff --git a/include/linux/memblock.h b/include/linux/memblock.h +index ae3bde302f704..ccf0176ba3681 100644 +--- a/include/linux/memblock.h ++++ b/include/linux/memblock.h +@@ -121,6 +121,8 @@ int memblock_reserve(phys_addr_t base, phys_addr_t size); + int memblock_physmem_add(phys_addr_t base, phys_addr_t size); + #endif + void memblock_trim_memory(phys_addr_t align); ++unsigned long memblock_addrs_overlap(phys_addr_t base1, phys_addr_t size1, ++ phys_addr_t base2, phys_addr_t size2); + bool memblock_overlaps_region(struct memblock_type *type, + phys_addr_t base, phys_addr_t size); + int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size); +diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h +index fb8d26a15df47..77cd2e13724e7 100644 +--- a/include/linux/mlx5/mlx5_ifc.h ++++ b/include/linux/mlx5/mlx5_ifc.h +@@ -1103,7 +1103,7 @@ struct mlx5_ifc_roce_cap_bits { + u8 sw_r_roce_src_udp_port[0x1]; + u8 fl_rc_qp_when_roce_disabled[0x1]; + u8 fl_rc_qp_when_roce_enabled[0x1]; +- u8 reserved_at_7[0x1]; ++ u8 roce_cc_general[0x1]; + u8 qp_ooo_transmit_default[0x1]; + u8 reserved_at_9[0x15]; + u8 qp_ts_format[0x2]; +diff --git a/include/linux/swap.h b/include/linux/swap.h +index f6dd6575b9054..e73285e3c8708 100644 +--- a/include/linux/swap.h ++++ b/include/linux/swap.h +@@ -553,6 +553,11 @@ static inline int swap_duplicate(swp_entry_t swp) + return 0; + } + ++static inline int swapcache_prepare(swp_entry_t swp) ++{ ++ return 0; ++} ++ + static inline void swap_free(swp_entry_t swp) + { + } +diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h +index 692d5955911c7..4a767b3d20b9d 100644 +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -275,7 +275,7 @@ nf_flow_table_offload_del_cb(struct nf_flowtable *flow_table, + } + + void flow_offload_route_init(struct flow_offload *flow, +- const struct nf_flow_route *route); ++ struct nf_flow_route *route); + + int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow); + void flow_offload_refresh(struct nf_flowtable *flow_table, +diff --git a/include/net/switchdev.h b/include/net/switchdev.h +index a43062d4c734b..8346b0d29542c 100644 +--- a/include/net/switchdev.h ++++ b/include/net/switchdev.h +@@ -308,6 +308,9 @@ void switchdev_deferred_process(void); + int switchdev_port_attr_set(struct net_device *dev, + const struct switchdev_attr *attr, + struct netlink_ext_ack *extack); ++bool switchdev_port_obj_act_is_deferred(struct net_device *dev, ++ enum switchdev_notifier_type nt, ++ const struct switchdev_obj *obj); + int switchdev_port_obj_add(struct net_device *dev, + const struct switchdev_obj *obj, + struct netlink_ext_ack *extack); +diff --git a/include/net/tcp.h b/include/net/tcp.h +index 87f0e6c2e1f2f..2ac9475be144c 100644 +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -2502,7 +2502,7 @@ struct tcp_ulp_ops { + /* cleanup ulp */ + void (*release)(struct sock *sk); + /* diagnostic */ +- int (*get_info)(const struct sock *sk, struct sk_buff *skb); ++ int (*get_info)(struct sock *sk, struct sk_buff *skb); + size_t (*get_info_size)(const struct sock *sk); + /* clone ulp */ + void (*clone)(const struct request_sock *req, struct sock *newsk, +diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h +index 5ec1e71a09de7..c38f4fe5e64cf 100644 +--- a/include/scsi/scsi_device.h ++++ b/include/scsi/scsi_device.h +@@ -100,10 +100,6 @@ struct scsi_vpd { + unsigned char data[]; + }; + +-enum scsi_vpd_parameters { +- SCSI_VPD_HEADER_SIZE = 4, +-}; +- + struct scsi_device { + struct Scsi_Host *host; + struct request_queue *request_queue; +@@ -208,6 +204,7 @@ struct scsi_device { + unsigned use_10_for_rw:1; /* first try 10-byte read / write */ + unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */ + unsigned set_dbd_for_ms:1; /* Set "DBD" field in mode sense */ ++ unsigned read_before_ms:1; /* perform a READ before MODE SENSE */ + unsigned no_report_opcodes:1; /* no REPORT SUPPORTED OPERATION CODES */ + unsigned no_write_same:1; /* no WRITE SAME command */ + unsigned use_16_for_rw:1; /* Use read/write(16) over read/write(10) */ +diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c +index b3053af6427d2..ce4729ef1ad2d 100644 +--- a/kernel/bpf/helpers.c ++++ b/kernel/bpf/helpers.c +@@ -1101,6 +1101,7 @@ struct bpf_hrtimer { + struct bpf_prog *prog; + void __rcu *callback_fn; + void *value; ++ struct rcu_head rcu; + }; + + /* the actual struct hidden inside uapi struct bpf_timer */ +@@ -1332,6 +1333,7 @@ BPF_CALL_1(bpf_timer_cancel, struct bpf_timer_kern *, timer) + + if (in_nmi()) + return -EOPNOTSUPP; ++ rcu_read_lock(); + __bpf_spin_lock_irqsave(&timer->lock); + t = timer->timer; + if (!t) { +@@ -1353,6 +1355,7 @@ BPF_CALL_1(bpf_timer_cancel, struct bpf_timer_kern *, timer) + * if it was running. + */ + ret = ret ?: hrtimer_cancel(&t->timer); ++ rcu_read_unlock(); + return ret; + } + +@@ -1407,7 +1410,7 @@ void bpf_timer_cancel_and_free(void *val) + */ + if (this_cpu_read(hrtimer_running) != t) + hrtimer_cancel(&t->timer); +- kfree(t); ++ kfree_rcu(t, rcu); + } + + BPF_CALL_2(bpf_kptr_xchg, void *, map_value, void *, ptr) +diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug +index 4405f81248fbc..ef39dffffd4bc 100644 +--- a/lib/Kconfig.debug ++++ b/lib/Kconfig.debug +@@ -2234,6 +2234,7 @@ config TEST_DIV64 + config TEST_IOV_ITER + tristate "Test iov_iter operation" if !KUNIT_ALL_TESTS + depends on KUNIT ++ depends on MMU + default KUNIT_ALL_TESTS + help + Enable this to turn on testing of the operation of the I/O iterator +diff --git a/lib/kunit/kunit-test.c b/lib/kunit/kunit-test.c +index de2113a58fa03..ee6927c609797 100644 +--- a/lib/kunit/kunit-test.c ++++ b/lib/kunit/kunit-test.c +@@ -538,10 +538,7 @@ static struct kunit_suite kunit_resource_test_suite = { + #if IS_BUILTIN(CONFIG_KUNIT_TEST) + + /* This avoids a cast warning if kfree() is passed direct to kunit_add_action(). */ +-static void kfree_wrapper(void *p) +-{ +- kfree(p); +-} ++KUNIT_DEFINE_ACTION_WRAPPER(kfree_wrapper, kfree, const void *); + + static void kunit_log_test(struct kunit *test) + { +diff --git a/lib/kunit/test.c b/lib/kunit/test.c +index 3dc9d66eca494..d6a2b2460d52d 100644 +--- a/lib/kunit/test.c ++++ b/lib/kunit/test.c +@@ -819,6 +819,8 @@ static struct notifier_block kunit_mod_nb = { + }; + #endif + ++KUNIT_DEFINE_ACTION_WRAPPER(kfree_action_wrapper, kfree, const void *) ++ + void *kunit_kmalloc_array(struct kunit *test, size_t n, size_t size, gfp_t gfp) + { + void *data; +@@ -828,7 +830,7 @@ void *kunit_kmalloc_array(struct kunit *test, size_t n, size_t size, gfp_t gfp) + if (!data) + return NULL; + +- if (kunit_add_action_or_reset(test, (kunit_action_t *)kfree, data) != 0) ++ if (kunit_add_action_or_reset(test, kfree_action_wrapper, data) != 0) + return NULL; + + return data; +@@ -840,7 +842,7 @@ void kunit_kfree(struct kunit *test, const void *ptr) + if (!ptr) + return; + +- kunit_release_action(test, (kunit_action_t *)kfree, (void *)ptr); ++ kunit_release_action(test, kfree_action_wrapper, (void *)ptr); + } + EXPORT_SYMBOL_GPL(kunit_kfree); + +diff --git a/mm/damon/core.c b/mm/damon/core.c +index 3a05e71509b9d..fb381835760c6 100644 +--- a/mm/damon/core.c ++++ b/mm/damon/core.c +@@ -1026,6 +1026,9 @@ static void damon_do_apply_schemes(struct damon_ctx *c, + damon_for_each_scheme(s, c) { + struct damos_quota *quota = &s->quota; + ++ if (c->passed_sample_intervals != s->next_apply_sis) ++ continue; ++ + if (!s->wmarks.activated) + continue; + +@@ -1126,10 +1129,6 @@ static void kdamond_apply_schemes(struct damon_ctx *c) + if (c->passed_sample_intervals != s->next_apply_sis) + continue; + +- s->next_apply_sis += +- (s->apply_interval_us ? s->apply_interval_us : +- c->attrs.aggr_interval) / sample_interval; +- + if (!s->wmarks.activated) + continue; + +@@ -1145,6 +1144,14 @@ static void kdamond_apply_schemes(struct damon_ctx *c) + damon_for_each_region_safe(r, next_r, t) + damon_do_apply_schemes(c, t, r); + } ++ ++ damon_for_each_scheme(s, c) { ++ if (c->passed_sample_intervals != s->next_apply_sis) ++ continue; ++ s->next_apply_sis += ++ (s->apply_interval_us ? s->apply_interval_us : ++ c->attrs.aggr_interval) / sample_interval; ++ } + } + + /* +diff --git a/mm/damon/lru_sort.c b/mm/damon/lru_sort.c +index f2e5f9431892e..3de2916a65c38 100644 +--- a/mm/damon/lru_sort.c ++++ b/mm/damon/lru_sort.c +@@ -185,9 +185,21 @@ static struct damos *damon_lru_sort_new_cold_scheme(unsigned int cold_thres) + return damon_lru_sort_new_scheme(&pattern, DAMOS_LRU_DEPRIO); + } + ++static void damon_lru_sort_copy_quota_status(struct damos_quota *dst, ++ struct damos_quota *src) ++{ ++ dst->total_charged_sz = src->total_charged_sz; ++ dst->total_charged_ns = src->total_charged_ns; ++ dst->charged_sz = src->charged_sz; ++ dst->charged_from = src->charged_from; ++ dst->charge_target_from = src->charge_target_from; ++ dst->charge_addr_from = src->charge_addr_from; ++} ++ + static int damon_lru_sort_apply_parameters(void) + { +- struct damos *scheme; ++ struct damos *scheme, *hot_scheme, *cold_scheme; ++ struct damos *old_hot_scheme = NULL, *old_cold_scheme = NULL; + unsigned int hot_thres, cold_thres; + int err = 0; + +@@ -195,18 +207,35 @@ static int damon_lru_sort_apply_parameters(void) + if (err) + return err; + ++ damon_for_each_scheme(scheme, ctx) { ++ if (!old_hot_scheme) { ++ old_hot_scheme = scheme; ++ continue; ++ } ++ old_cold_scheme = scheme; ++ } ++ + hot_thres = damon_max_nr_accesses(&damon_lru_sort_mon_attrs) * + hot_thres_access_freq / 1000; +- scheme = damon_lru_sort_new_hot_scheme(hot_thres); +- if (!scheme) ++ hot_scheme = damon_lru_sort_new_hot_scheme(hot_thres); ++ if (!hot_scheme) + return -ENOMEM; +- damon_set_schemes(ctx, &scheme, 1); ++ if (old_hot_scheme) ++ damon_lru_sort_copy_quota_status(&hot_scheme->quota, ++ &old_hot_scheme->quota); + + cold_thres = cold_min_age / damon_lru_sort_mon_attrs.aggr_interval; +- scheme = damon_lru_sort_new_cold_scheme(cold_thres); +- if (!scheme) ++ cold_scheme = damon_lru_sort_new_cold_scheme(cold_thres); ++ if (!cold_scheme) { ++ damon_destroy_scheme(hot_scheme); + return -ENOMEM; +- damon_add_scheme(ctx, scheme); ++ } ++ if (old_cold_scheme) ++ damon_lru_sort_copy_quota_status(&cold_scheme->quota, ++ &old_cold_scheme->quota); ++ ++ damon_set_schemes(ctx, &hot_scheme, 1); ++ damon_add_scheme(ctx, cold_scheme); + + return damon_set_region_biggest_system_ram_default(target, + &monitor_region_start, +diff --git a/mm/damon/reclaim.c b/mm/damon/reclaim.c +index ab974e477d2f2..66e190f0374ac 100644 +--- a/mm/damon/reclaim.c ++++ b/mm/damon/reclaim.c +@@ -150,9 +150,20 @@ static struct damos *damon_reclaim_new_scheme(void) + &damon_reclaim_wmarks); + } + ++static void damon_reclaim_copy_quota_status(struct damos_quota *dst, ++ struct damos_quota *src) ++{ ++ dst->total_charged_sz = src->total_charged_sz; ++ dst->total_charged_ns = src->total_charged_ns; ++ dst->charged_sz = src->charged_sz; ++ dst->charged_from = src->charged_from; ++ dst->charge_target_from = src->charge_target_from; ++ dst->charge_addr_from = src->charge_addr_from; ++} ++ + static int damon_reclaim_apply_parameters(void) + { +- struct damos *scheme; ++ struct damos *scheme, *old_scheme; + struct damos_filter *filter; + int err = 0; + +@@ -164,6 +175,11 @@ static int damon_reclaim_apply_parameters(void) + scheme = damon_reclaim_new_scheme(); + if (!scheme) + return -ENOMEM; ++ if (!list_empty(&ctx->schemes)) { ++ damon_for_each_scheme(old_scheme, ctx) ++ damon_reclaim_copy_quota_status(&scheme->quota, ++ &old_scheme->quota); ++ } + if (skip_anon) { + filter = damos_new_filter(DAMOS_FILTER_TYPE_ANON, true); + if (!filter) { +diff --git a/mm/memblock.c b/mm/memblock.c +index 4823ad979b72f..9a5248fe9cf97 100644 +--- a/mm/memblock.c ++++ b/mm/memblock.c +@@ -180,8 +180,9 @@ static inline phys_addr_t memblock_cap_size(phys_addr_t base, phys_addr_t *size) + /* + * Address comparison utilities + */ +-static unsigned long __init_memblock memblock_addrs_overlap(phys_addr_t base1, phys_addr_t size1, +- phys_addr_t base2, phys_addr_t size2) ++unsigned long __init_memblock ++memblock_addrs_overlap(phys_addr_t base1, phys_addr_t size1, phys_addr_t base2, ++ phys_addr_t size2) + { + return ((base1 < (base2 + size2)) && (base2 < (base1 + size1))); + } +@@ -2214,6 +2215,7 @@ static const char * const flagname[] = { + [ilog2(MEMBLOCK_MIRROR)] = "MIRROR", + [ilog2(MEMBLOCK_NOMAP)] = "NOMAP", + [ilog2(MEMBLOCK_DRIVER_MANAGED)] = "DRV_MNG", ++ [ilog2(MEMBLOCK_RSRV_NOINIT)] = "RSV_NIT", + }; + + static int memblock_debug_show(struct seq_file *m, void *private) +diff --git a/mm/memcontrol.c b/mm/memcontrol.c +index 651b86ff03dd1..792fb3a5ce3b9 100644 +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -7905,9 +7905,13 @@ bool mem_cgroup_swap_full(struct folio *folio) + + static int __init setup_swap_account(char *s) + { +- pr_warn_once("The swapaccount= commandline option is deprecated. " +- "Please report your usecase to linux-mm@kvack.org if you " +- "depend on this functionality.\n"); ++ bool res; ++ ++ if (!kstrtobool(s, &res) && !res) ++ pr_warn_once("The swapaccount=0 commandline option is deprecated " ++ "in favor of configuring swap control via cgroupfs. " ++ "Please report your usecase to linux-mm@kvack.org if you " ++ "depend on this functionality.\n"); + return 1; + } + __setup("swapaccount=", setup_swap_account); +diff --git a/mm/memory.c b/mm/memory.c +index f941489d60414..ec7b775fb4313 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -3785,6 +3785,7 @@ vm_fault_t do_swap_page(struct vm_fault *vmf) + struct page *page; + struct swap_info_struct *si = NULL; + rmap_t rmap_flags = RMAP_NONE; ++ bool need_clear_cache = false; + bool exclusive = false; + swp_entry_t entry; + pte_t pte; +@@ -3853,6 +3854,20 @@ vm_fault_t do_swap_page(struct vm_fault *vmf) + if (!folio) { + if (data_race(si->flags & SWP_SYNCHRONOUS_IO) && + __swap_count(entry) == 1) { ++ /* ++ * Prevent parallel swapin from proceeding with ++ * the cache flag. Otherwise, another thread may ++ * finish swapin first, free the entry, and swapout ++ * reusing the same entry. It's undetectable as ++ * pte_same() returns true due to entry reuse. ++ */ ++ if (swapcache_prepare(entry)) { ++ /* Relax a bit to prevent rapid repeated page faults */ ++ schedule_timeout_uninterruptible(1); ++ goto out; ++ } ++ need_clear_cache = true; ++ + /* skip swapcache */ + folio = vma_alloc_folio(GFP_HIGHUSER_MOVABLE, 0, + vma, vmf->address, false); +@@ -4099,6 +4114,9 @@ vm_fault_t do_swap_page(struct vm_fault *vmf) + if (vmf->pte) + pte_unmap_unlock(vmf->pte, vmf->ptl); + out: ++ /* Clear the swap cache pin for direct swapin after PTL unlock */ ++ if (need_clear_cache) ++ swapcache_clear(si, entry); + if (si) + put_swap_device(si); + return ret; +@@ -4113,6 +4131,8 @@ vm_fault_t do_swap_page(struct vm_fault *vmf) + folio_unlock(swapcache); + folio_put(swapcache); + } ++ if (need_clear_cache) ++ swapcache_clear(si, entry); + if (si) + put_swap_device(si); + return ret; +diff --git a/mm/swap.h b/mm/swap.h +index 73c332ee4d910..3501fdf5f1a6e 100644 +--- a/mm/swap.h ++++ b/mm/swap.h +@@ -40,6 +40,7 @@ void __delete_from_swap_cache(struct folio *folio, + void delete_from_swap_cache(struct folio *folio); + void clear_shadow_from_swap_cache(int type, unsigned long begin, + unsigned long end); ++void swapcache_clear(struct swap_info_struct *si, swp_entry_t entry); + struct folio *swap_cache_get_folio(swp_entry_t entry, + struct vm_area_struct *vma, unsigned long addr); + struct folio *filemap_get_incore_folio(struct address_space *mapping, +@@ -97,6 +98,10 @@ static inline int swap_writepage(struct page *p, struct writeback_control *wbc) + return 0; + } + ++static inline void swapcache_clear(struct swap_info_struct *si, swp_entry_t entry) ++{ ++} ++ + static inline struct folio *swap_cache_get_folio(swp_entry_t entry, + struct vm_area_struct *vma, unsigned long addr) + { +diff --git a/mm/swapfile.c b/mm/swapfile.c +index 4bc70f4591641..022581ec40be3 100644 +--- a/mm/swapfile.c ++++ b/mm/swapfile.c +@@ -3363,6 +3363,19 @@ int swapcache_prepare(swp_entry_t entry) + return __swap_duplicate(entry, SWAP_HAS_CACHE); + } + ++void swapcache_clear(struct swap_info_struct *si, swp_entry_t entry) ++{ ++ struct swap_cluster_info *ci; ++ unsigned long offset = swp_offset(entry); ++ unsigned char usage; ++ ++ ci = lock_cluster_or_swap_info(si, offset); ++ usage = __swap_entry_free_locked(si, offset, SWAP_HAS_CACHE); ++ unlock_cluster_or_swap_info(si, ci); ++ if (!usage) ++ free_swap_slot(entry); ++} ++ + struct swap_info_struct *swp_swap_info(swp_entry_t entry) + { + return swap_type_to_swap_info(swp_type(entry)); +diff --git a/mm/zswap.c b/mm/zswap.c +index 74411dfdad925..870fd6f5a5bb9 100644 +--- a/mm/zswap.c ++++ b/mm/zswap.c +@@ -1105,6 +1105,8 @@ static int zswap_writeback_entry(struct zswap_entry *entry, + if (zswap_rb_search(&tree->rbroot, swp_offset(entry->swpentry)) != entry) { + spin_unlock(&tree->lock); + delete_from_swap_cache(page_folio(page)); ++ unlock_page(page); ++ put_page(page); + ret = -ENOMEM; + goto fail; + } +@@ -1220,7 +1222,7 @@ bool zswap_store(struct folio *folio) + if (folio_test_large(folio)) + return false; + +- if (!zswap_enabled || !tree) ++ if (!tree) + return false; + + /* +@@ -1236,6 +1238,9 @@ bool zswap_store(struct folio *folio) + } + spin_unlock(&tree->lock); + ++ if (!zswap_enabled) ++ return false; ++ + /* + * XXX: zswap reclaim does not work with cgroups yet. Without a + * cgroup-aware entry LRU, we will push out entries system-wide based on +diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c +index ee84e783e1dff..7b41ee8740cbb 100644 +--- a/net/bridge/br_switchdev.c ++++ b/net/bridge/br_switchdev.c +@@ -595,21 +595,40 @@ br_switchdev_mdb_replay_one(struct notifier_block *nb, struct net_device *dev, + } + + static int br_switchdev_mdb_queue_one(struct list_head *mdb_list, ++ struct net_device *dev, ++ unsigned long action, + enum switchdev_obj_id id, + const struct net_bridge_mdb_entry *mp, + struct net_device *orig_dev) + { +- struct switchdev_obj_port_mdb *mdb; ++ struct switchdev_obj_port_mdb mdb = { ++ .obj = { ++ .id = id, ++ .orig_dev = orig_dev, ++ }, ++ }; ++ struct switchdev_obj_port_mdb *pmdb; + +- mdb = kzalloc(sizeof(*mdb), GFP_ATOMIC); +- if (!mdb) +- return -ENOMEM; ++ br_switchdev_mdb_populate(&mdb, mp); ++ ++ if (action == SWITCHDEV_PORT_OBJ_ADD && ++ switchdev_port_obj_act_is_deferred(dev, action, &mdb.obj)) { ++ /* This event is already in the deferred queue of ++ * events, so this replay must be elided, lest the ++ * driver receives duplicate events for it. This can ++ * only happen when replaying additions, since ++ * modifications are always immediately visible in ++ * br->mdb_list, whereas actual event delivery may be ++ * delayed. ++ */ ++ return 0; ++ } + +- mdb->obj.id = id; +- mdb->obj.orig_dev = orig_dev; +- br_switchdev_mdb_populate(mdb, mp); +- list_add_tail(&mdb->obj.list, mdb_list); ++ pmdb = kmemdup(&mdb, sizeof(mdb), GFP_ATOMIC); ++ if (!pmdb) ++ return -ENOMEM; + ++ list_add_tail(&pmdb->obj.list, mdb_list); + return 0; + } + +@@ -677,51 +696,50 @@ br_switchdev_mdb_replay(struct net_device *br_dev, struct net_device *dev, + if (!br_opt_get(br, BROPT_MULTICAST_ENABLED)) + return 0; + +- /* We cannot walk over br->mdb_list protected just by the rtnl_mutex, +- * because the write-side protection is br->multicast_lock. But we +- * need to emulate the [ blocking ] calling context of a regular +- * switchdev event, so since both br->multicast_lock and RCU read side +- * critical sections are atomic, we have no choice but to pick the RCU +- * read side lock, queue up all our events, leave the critical section +- * and notify switchdev from blocking context. ++ if (adding) ++ action = SWITCHDEV_PORT_OBJ_ADD; ++ else ++ action = SWITCHDEV_PORT_OBJ_DEL; ++ ++ /* br_switchdev_mdb_queue_one() will take care to not queue a ++ * replay of an event that is already pending in the switchdev ++ * deferred queue. In order to safely determine that, there ++ * must be no new deferred MDB notifications enqueued for the ++ * duration of the MDB scan. Therefore, grab the write-side ++ * lock to avoid racing with any concurrent IGMP/MLD snooping. + */ +- rcu_read_lock(); ++ spin_lock_bh(&br->multicast_lock); + +- hlist_for_each_entry_rcu(mp, &br->mdb_list, mdb_node) { ++ hlist_for_each_entry(mp, &br->mdb_list, mdb_node) { + struct net_bridge_port_group __rcu * const *pp; + const struct net_bridge_port_group *p; + + if (mp->host_joined) { +- err = br_switchdev_mdb_queue_one(&mdb_list, ++ err = br_switchdev_mdb_queue_one(&mdb_list, dev, action, + SWITCHDEV_OBJ_ID_HOST_MDB, + mp, br_dev); + if (err) { +- rcu_read_unlock(); ++ spin_unlock_bh(&br->multicast_lock); + goto out_free_mdb; + } + } + +- for (pp = &mp->ports; (p = rcu_dereference(*pp)) != NULL; ++ for (pp = &mp->ports; (p = mlock_dereference(*pp, br)) != NULL; + pp = &p->next) { + if (p->key.port->dev != dev) + continue; + +- err = br_switchdev_mdb_queue_one(&mdb_list, ++ err = br_switchdev_mdb_queue_one(&mdb_list, dev, action, + SWITCHDEV_OBJ_ID_PORT_MDB, + mp, dev); + if (err) { +- rcu_read_unlock(); ++ spin_unlock_bh(&br->multicast_lock); + goto out_free_mdb; + } + } + } + +- rcu_read_unlock(); +- +- if (adding) +- action = SWITCHDEV_PORT_OBJ_ADD; +- else +- action = SWITCHDEV_PORT_OBJ_DEL; ++ spin_unlock_bh(&br->multicast_lock); + + list_for_each_entry(obj, &mdb_list, list) { + err = br_switchdev_mdb_replay_one(nb, dev, +@@ -786,6 +804,16 @@ static void nbp_switchdev_unsync_objs(struct net_bridge_port *p, + br_switchdev_mdb_replay(br_dev, dev, ctx, false, blocking_nb, NULL); + + br_switchdev_vlan_replay(br_dev, ctx, false, blocking_nb, NULL); ++ ++ /* Make sure that the device leaving this bridge has seen all ++ * relevant events before it is disassociated. In the normal ++ * case, when the device is directly attached to the bridge, ++ * this is covered by del_nbp(). If the association was indirect ++ * however, e.g. via a team or bond, and the device is leaving ++ * that intermediate device, then the bridge port remains in ++ * place. ++ */ ++ switchdev_deferred_process(); + } + + /* Let the bridge know that this port is offloaded, so that it can assign a +diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c +index 8d9760397b887..3babcd5e65e16 100644 +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -5856,8 +5856,8 @@ static int osd_sparse_read(struct ceph_connection *con, + struct ceph_osd *o = con->private; + struct ceph_sparse_read *sr = &o->o_sparse_read; + u32 count = sr->sr_count; +- u64 eoff, elen; +- int ret; ++ u64 eoff, elen, len = 0; ++ int i, ret; + + switch (sr->sr_state) { + case CEPH_SPARSE_READ_HDR: +@@ -5909,8 +5909,20 @@ static int osd_sparse_read(struct ceph_connection *con, + convert_extent_map(sr); + ret = sizeof(sr->sr_datalen); + *pbuf = (char *)&sr->sr_datalen; +- sr->sr_state = CEPH_SPARSE_READ_DATA; ++ sr->sr_state = CEPH_SPARSE_READ_DATA_PRE; + break; ++ case CEPH_SPARSE_READ_DATA_PRE: ++ /* Convert sr_datalen to host-endian */ ++ sr->sr_datalen = le32_to_cpu((__force __le32)sr->sr_datalen); ++ for (i = 0; i < count; i++) ++ len += sr->sr_extent[i].len; ++ if (sr->sr_datalen != len) { ++ pr_warn_ratelimited("data len %u != extent len %llu\n", ++ sr->sr_datalen, len); ++ return -EREMOTEIO; ++ } ++ sr->sr_state = CEPH_SPARSE_READ_DATA; ++ fallthrough; + case CEPH_SPARSE_READ_DATA: + if (sr->sr_index >= count) { + sr->sr_state = CEPH_SPARSE_READ_HDR; +diff --git a/net/core/skmsg.c b/net/core/skmsg.c +index 93ecfceac1bc4..4d75ef9d24bfa 100644 +--- a/net/core/skmsg.c ++++ b/net/core/skmsg.c +@@ -1226,8 +1226,11 @@ static void sk_psock_verdict_data_ready(struct sock *sk) + + rcu_read_lock(); + psock = sk_psock(sk); +- if (psock) +- psock->saved_data_ready(sk); ++ if (psock) { ++ read_lock_bh(&sk->sk_callback_lock); ++ sk_psock_data_ready(sk, psock); ++ read_unlock_bh(&sk->sk_callback_lock); ++ } + rcu_read_unlock(); + } + } +diff --git a/net/core/sock.c b/net/core/sock.c +index e5d43a068f8ed..20160865ede9c 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -1192,6 +1192,17 @@ int sk_setsockopt(struct sock *sk, int level, int optname, + */ + WRITE_ONCE(sk->sk_txrehash, (u8)val); + return 0; ++ case SO_PEEK_OFF: ++ { ++ int (*set_peek_off)(struct sock *sk, int val); ++ ++ set_peek_off = READ_ONCE(sock->ops)->set_peek_off; ++ if (set_peek_off) ++ ret = set_peek_off(sk, val); ++ else ++ ret = -EOPNOTSUPP; ++ return ret; ++ } + } + + sockopt_lock_sock(sk); +@@ -1434,18 +1445,6 @@ int sk_setsockopt(struct sock *sk, int level, int optname, + sock_valbool_flag(sk, SOCK_WIFI_STATUS, valbool); + break; + +- case SO_PEEK_OFF: +- { +- int (*set_peek_off)(struct sock *sk, int val); +- +- set_peek_off = READ_ONCE(sock->ops)->set_peek_off; +- if (set_peek_off) +- ret = set_peek_off(sk, val); +- else +- ret = -EOPNOTSUPP; +- break; +- } +- + case SO_NOFCS: + sock_valbool_flag(sk, SOCK_NOFCS, valbool); + break; +diff --git a/net/devlink/core.c b/net/devlink/core.c +index cbf8560c93752..bc3d265fe2d6e 100644 +--- a/net/devlink/core.c ++++ b/net/devlink/core.c +@@ -529,14 +529,20 @@ static int __init devlink_init(void) + { + int err; + +- err = genl_register_family(&devlink_nl_family); +- if (err) +- goto out; + err = register_pernet_subsys(&devlink_pernet_ops); + if (err) + goto out; ++ err = genl_register_family(&devlink_nl_family); ++ if (err) ++ goto out_unreg_pernet_subsys; + err = register_netdevice_notifier(&devlink_port_netdevice_nb); ++ if (!err) ++ return 0; ++ ++ genl_unregister_family(&devlink_nl_family); + ++out_unreg_pernet_subsys: ++ unregister_pernet_subsys(&devlink_pernet_ops); + out: + WARN_ON(err); + return err; +diff --git a/net/devlink/port.c b/net/devlink/port.c +index 841a3eafa328e..d39ee6053cc7b 100644 +--- a/net/devlink/port.c ++++ b/net/devlink/port.c +@@ -581,7 +581,7 @@ devlink_nl_port_get_dump_one(struct sk_buff *msg, struct devlink *devlink, + + xa_for_each_start(&devlink->ports, port_index, devlink_port, state->idx) { + err = devlink_nl_port_fill(msg, devlink_port, +- DEVLINK_CMD_NEW, ++ DEVLINK_CMD_PORT_NEW, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, flags, + cb->extack); +diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c +index 9456f5bb35e5d..0d0d725b46ad0 100644 +--- a/net/ipv4/arp.c ++++ b/net/ipv4/arp.c +@@ -1125,7 +1125,8 @@ static int arp_req_get(struct arpreq *r, struct net_device *dev) + if (neigh) { + if (!(READ_ONCE(neigh->nud_state) & NUD_NOARP)) { + read_lock_bh(&neigh->lock); +- memcpy(r->arp_ha.sa_data, neigh->ha, dev->addr_len); ++ memcpy(r->arp_ha.sa_data, neigh->ha, ++ min(dev->addr_len, sizeof(r->arp_ha.sa_data_min))); + r->arp_flags = arp_state_to_flags(neigh); + read_unlock_bh(&neigh->lock); + r->arp_ha.sa_family = dev->type; +diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c +index ca0ff15dc8fa3..bc74f131fe4df 100644 +--- a/net/ipv4/devinet.c ++++ b/net/ipv4/devinet.c +@@ -1825,6 +1825,21 @@ static int in_dev_dump_addr(struct in_device *in_dev, struct sk_buff *skb, + return err; + } + ++/* Combine dev_addr_genid and dev_base_seq to detect changes. ++ */ ++static u32 inet_base_seq(const struct net *net) ++{ ++ u32 res = atomic_read(&net->ipv4.dev_addr_genid) + ++ net->dev_base_seq; ++ ++ /* Must not return 0 (see nl_dump_check_consistent()). ++ * Chose a value far away from 0. ++ */ ++ if (!res) ++ res = 0x80000000; ++ return res; ++} ++ + static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) + { + const struct nlmsghdr *nlh = cb->nlh; +@@ -1876,8 +1891,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) + idx = 0; + head = &tgt_net->dev_index_head[h]; + rcu_read_lock(); +- cb->seq = atomic_read(&tgt_net->ipv4.dev_addr_genid) ^ +- tgt_net->dev_base_seq; ++ cb->seq = inet_base_seq(tgt_net); + hlist_for_each_entry_rcu(dev, head, index_hlist) { + if (idx < s_idx) + goto cont; +@@ -2278,8 +2292,7 @@ static int inet_netconf_dump_devconf(struct sk_buff *skb, + idx = 0; + head = &net->dev_index_head[h]; + rcu_read_lock(); +- cb->seq = atomic_read(&net->ipv4.dev_addr_genid) ^ +- net->dev_base_seq; ++ cb->seq = inet_base_seq(net); + hlist_for_each_entry_rcu(dev, head, index_hlist) { + if (idx < s_idx) + goto cont; +diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c +index a532f749e4778..9456bf9e2705b 100644 +--- a/net/ipv4/inet_hashtables.c ++++ b/net/ipv4/inet_hashtables.c +@@ -1131,10 +1131,33 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row, + return 0; + + error: ++ if (sk_hashed(sk)) { ++ spinlock_t *lock = inet_ehash_lockp(hinfo, sk->sk_hash); ++ ++ sock_prot_inuse_add(net, sk->sk_prot, -1); ++ ++ spin_lock(lock); ++ sk_nulls_del_node_init_rcu(sk); ++ spin_unlock(lock); ++ ++ sk->sk_hash = 0; ++ inet_sk(sk)->inet_sport = 0; ++ inet_sk(sk)->inet_num = 0; ++ ++ if (tw) ++ inet_twsk_bind_unhash(tw, hinfo); ++ } ++ + spin_unlock(&head2->lock); + if (tb_created) + inet_bind_bucket_destroy(hinfo->bind_bucket_cachep, tb); +- spin_unlock_bh(&head->lock); ++ spin_unlock(&head->lock); ++ ++ if (tw) ++ inet_twsk_deschedule_put(tw); ++ ++ local_bh_enable(); ++ + return -ENOMEM; + } + +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index f631b0a21af4c..e474b201900f9 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -1589,12 +1589,7 @@ int udp_init_sock(struct sock *sk) + + void skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len) + { +- if (unlikely(READ_ONCE(sk->sk_peek_off) >= 0)) { +- bool slow = lock_sock_fast(sk); +- +- sk_peek_offset_bwd(sk, len); +- unlock_sock_fast(sk, slow); +- } ++ sk_peek_offset_bwd(sk, len); + + if (!skb_unref(skb)) + return; +diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c +index 733ace18806c6..5a839c5fb1a5a 100644 +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -708,6 +708,22 @@ static int inet6_netconf_get_devconf(struct sk_buff *in_skb, + return err; + } + ++/* Combine dev_addr_genid and dev_base_seq to detect changes. ++ */ ++static u32 inet6_base_seq(const struct net *net) ++{ ++ u32 res = atomic_read(&net->ipv6.dev_addr_genid) + ++ net->dev_base_seq; ++ ++ /* Must not return 0 (see nl_dump_check_consistent()). ++ * Chose a value far away from 0. ++ */ ++ if (!res) ++ res = 0x80000000; ++ return res; ++} ++ ++ + static int inet6_netconf_dump_devconf(struct sk_buff *skb, + struct netlink_callback *cb) + { +@@ -741,8 +757,7 @@ static int inet6_netconf_dump_devconf(struct sk_buff *skb, + idx = 0; + head = &net->dev_index_head[h]; + rcu_read_lock(); +- cb->seq = atomic_read(&net->ipv6.dev_addr_genid) ^ +- net->dev_base_seq; ++ cb->seq = inet6_base_seq(net); + hlist_for_each_entry_rcu(dev, head, index_hlist) { + if (idx < s_idx) + goto cont; +@@ -5362,7 +5377,7 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb, + } + + rcu_read_lock(); +- cb->seq = atomic_read(&tgt_net->ipv6.dev_addr_genid) ^ tgt_net->dev_base_seq; ++ cb->seq = inet6_base_seq(tgt_net); + for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { + idx = 0; + head = &tgt_net->dev_index_head[h]; +diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c +index 4952ae7924505..02e9ffb63af19 100644 +--- a/net/ipv6/exthdrs.c ++++ b/net/ipv6/exthdrs.c +@@ -177,6 +177,8 @@ static bool ip6_parse_tlv(bool hopbyhop, + case IPV6_TLV_IOAM: + if (!ipv6_hop_ioam(skb, off)) + return false; ++ ++ nh = skb_network_header(skb); + break; + case IPV6_TLV_JUMBO: + if (!ipv6_hop_jumbo(skb, off)) +@@ -943,6 +945,14 @@ static bool ipv6_hop_ioam(struct sk_buff *skb, int optoff) + if (!skb_valid_dst(skb)) + ip6_route_input(skb); + ++ /* About to mangle packet header */ ++ if (skb_ensure_writable(skb, optoff + 2 + hdr->opt_len)) ++ goto drop; ++ ++ /* Trace pointer may have changed */ ++ trace = (struct ioam6_trace_hdr *)(skb_network_header(skb) ++ + optoff + sizeof(*hdr)); ++ + ioam6_fill_trace_data(skb, ns, trace, true); + break; + default: +diff --git a/net/ipv6/seg6.c b/net/ipv6/seg6.c +index 29346a6eec9ff..35508abd76f43 100644 +--- a/net/ipv6/seg6.c ++++ b/net/ipv6/seg6.c +@@ -512,22 +512,24 @@ int __init seg6_init(void) + { + int err; + +- err = genl_register_family(&seg6_genl_family); ++ err = register_pernet_subsys(&ip6_segments_ops); + if (err) + goto out; + +- err = register_pernet_subsys(&ip6_segments_ops); ++ err = genl_register_family(&seg6_genl_family); + if (err) +- goto out_unregister_genl; ++ goto out_unregister_pernet; + + #ifdef CONFIG_IPV6_SEG6_LWTUNNEL + err = seg6_iptunnel_init(); + if (err) +- goto out_unregister_pernet; ++ goto out_unregister_genl; + + err = seg6_local_init(); +- if (err) +- goto out_unregister_pernet; ++ if (err) { ++ seg6_iptunnel_exit(); ++ goto out_unregister_genl; ++ } + #endif + + #ifdef CONFIG_IPV6_SEG6_HMAC +@@ -548,11 +550,11 @@ int __init seg6_init(void) + #endif + #endif + #ifdef CONFIG_IPV6_SEG6_LWTUNNEL +-out_unregister_pernet: +- unregister_pernet_subsys(&ip6_segments_ops); +-#endif + out_unregister_genl: + genl_unregister_family(&seg6_genl_family); ++#endif ++out_unregister_pernet: ++ unregister_pernet_subsys(&ip6_segments_ops); + goto out; + } + +diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c +index bb373e249237a..763a59414b163 100644 +--- a/net/l2tp/l2tp_ip6.c ++++ b/net/l2tp/l2tp_ip6.c +@@ -627,7 +627,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) + + back_from_confirm: + lock_sock(sk); +- ulen = len + skb_queue_empty(&sk->sk_write_queue) ? transhdrlen : 0; ++ ulen = len + (skb_queue_empty(&sk->sk_write_queue) ? transhdrlen : 0); + err = ip6_append_data(sk, ip_generic_getfrag, msg, + ulen, transhdrlen, &ipc6, + &fl6, (struct rt6_info *)dst, +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index bfb06dea43c2d..b382c2e0a39a0 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1869,6 +1869,8 @@ static int sta_link_apply_parameters(struct ieee80211_local *local, + sband->band); + } + ++ ieee80211_sta_set_rx_nss(link_sta); ++ + return ret; + } + +diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c +index dce5606ed66da..68596ef78b15e 100644 +--- a/net/mac80211/debugfs_netdev.c ++++ b/net/mac80211/debugfs_netdev.c +@@ -997,8 +997,8 @@ static void add_link_files(struct ieee80211_link_data *link, + } + } + +-void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata, +- bool mld_vif) ++static void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata, ++ bool mld_vif) + { + char buf[10+IFNAMSIZ]; + +diff --git a/net/mac80211/debugfs_netdev.h b/net/mac80211/debugfs_netdev.h +index b226b1aae88a5..a02ec0a413f61 100644 +--- a/net/mac80211/debugfs_netdev.h ++++ b/net/mac80211/debugfs_netdev.h +@@ -11,8 +11,6 @@ + #include "ieee80211_i.h" + + #ifdef CONFIG_MAC80211_DEBUGFS +-void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata, +- bool mld_vif); + void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata); + void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata); + void ieee80211_debugfs_recreate_netdev(struct ieee80211_sub_if_data *sdata, +@@ -24,9 +22,6 @@ void ieee80211_link_debugfs_remove(struct ieee80211_link_data *link); + void ieee80211_link_debugfs_drv_add(struct ieee80211_link_data *link); + void ieee80211_link_debugfs_drv_remove(struct ieee80211_link_data *link); + #else +-static inline void ieee80211_debugfs_add_netdev( +- struct ieee80211_sub_if_data *sdata, bool mld_vif) +-{} + static inline void ieee80211_debugfs_remove_netdev( + struct ieee80211_sub_if_data *sdata) + {} +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index e4e7c0b38cb6e..11c4caa4748e4 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -1783,7 +1783,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, + /* need to do this after the switch so vif.type is correct */ + ieee80211_link_setup(&sdata->deflink); + +- ieee80211_debugfs_add_netdev(sdata, false); ++ ieee80211_debugfs_recreate_netdev(sdata, false); + } + + static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 5a03bf1de6bb7..241e615189244 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -8,7 +8,7 @@ + * Copyright 2007, Michael Wu <flamingice@sourmilk.net> + * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright (C) 2015 - 2017 Intel Deutschland GmbH +- * Copyright (C) 2018 - 2023 Intel Corporation ++ * Copyright (C) 2018 - 2024 Intel Corporation + */ + + #include <linux/delay.h> +@@ -2903,6 +2903,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, + + /* other links will be destroyed */ + sdata->deflink.u.mgd.bss = NULL; ++ sdata->deflink.smps_mode = IEEE80211_SMPS_OFF; + + netif_carrier_off(sdata->dev); + +@@ -5030,9 +5031,6 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, + if (!link) + return 0; + +- /* will change later if needed */ +- link->smps_mode = IEEE80211_SMPS_OFF; +- + /* + * If this fails (possibly due to channel context sharing + * on incompatible channels, e.g. 80+80 and 160 sharing the +@@ -7075,6 +7073,7 @@ void ieee80211_mgd_setup_link(struct ieee80211_link_data *link) + link->u.mgd.p2p_noa_index = -1; + link->u.mgd.conn_flags = 0; + link->conf->bssid = link->u.mgd.bssid; ++ link->smps_mode = IEEE80211_SMPS_OFF; + + wiphy_work_init(&link->u.mgd.request_smps_work, + ieee80211_request_smps_mgd_work); +@@ -8106,6 +8105,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, + ieee80211_report_disconnect(sdata, frame_buf, + sizeof(frame_buf), true, + req->reason_code, false); ++ drv_mgd_complete_tx(sdata->local, sdata, &info); + return 0; + } + +diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c +index 24fa06105378d..fca3f67ac0e8e 100644 +--- a/net/mac80211/scan.c ++++ b/net/mac80211/scan.c +@@ -9,7 +9,7 @@ + * Copyright 2007, Michael Wu <flamingice@sourmilk.net> + * Copyright 2013-2015 Intel Mobile Communications GmbH + * Copyright 2016-2017 Intel Deutschland GmbH +- * Copyright (C) 2018-2023 Intel Corporation ++ * Copyright (C) 2018-2024 Intel Corporation + */ + + #include <linux/if_arp.h> +@@ -216,14 +216,18 @@ ieee80211_bss_info_update(struct ieee80211_local *local, + } + + static bool ieee80211_scan_accept_presp(struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_channel *channel, + u32 scan_flags, const u8 *da) + { + if (!sdata) + return false; +- /* accept broadcast for OCE */ +- if (scan_flags & NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP && +- is_broadcast_ether_addr(da)) ++ ++ /* accept broadcast on 6 GHz and for OCE */ ++ if (is_broadcast_ether_addr(da) && ++ (channel->band == NL80211_BAND_6GHZ || ++ scan_flags & NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP)) + return true; ++ + if (scan_flags & NL80211_SCAN_FLAG_RANDOM_ADDR) + return true; + return ether_addr_equal(da, sdata->vif.addr); +@@ -272,6 +276,12 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) + wiphy_delayed_work_queue(local->hw.wiphy, &local->scan_work, 0); + } + ++ channel = ieee80211_get_channel_khz(local->hw.wiphy, ++ ieee80211_rx_status_to_khz(rx_status)); ++ ++ if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) ++ return; ++ + if (ieee80211_is_probe_resp(mgmt->frame_control)) { + struct cfg80211_scan_request *scan_req; + struct cfg80211_sched_scan_request *sched_scan_req; +@@ -289,19 +299,15 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) + /* ignore ProbeResp to foreign address or non-bcast (OCE) + * unless scanning with randomised address + */ +- if (!ieee80211_scan_accept_presp(sdata1, scan_req_flags, ++ if (!ieee80211_scan_accept_presp(sdata1, channel, ++ scan_req_flags, + mgmt->da) && +- !ieee80211_scan_accept_presp(sdata2, sched_scan_req_flags, ++ !ieee80211_scan_accept_presp(sdata2, channel, ++ sched_scan_req_flags, + mgmt->da)) + return; + } + +- channel = ieee80211_get_channel_khz(local->hw.wiphy, +- ieee80211_rx_status_to_khz(rx_status)); +- +- if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) +- return; +- + bss = ieee80211_bss_info_update(local, rx_status, + mgmt, skb->len, + channel); +diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c +index c33decbb97f2d..bcf3f727fc6da 100644 +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -913,6 +913,8 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) + if (ieee80211_vif_is_mesh(&sdata->vif)) + mesh_accept_plinks_update(sdata); + ++ ieee80211_check_fast_xmit(sta); ++ + return 0; + out_remove: + if (sta->sta.valid_links) +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index d7aa75b7fd917..a85918594cbe2 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -3048,7 +3048,7 @@ void ieee80211_check_fast_xmit(struct sta_info *sta) + sdata->vif.type == NL80211_IFTYPE_STATION) + goto out; + +- if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED)) ++ if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED) || !sta->uploaded) + goto out; + + if (test_sta_flag(sta, WLAN_STA_PS_STA) || +diff --git a/net/mctp/route.c b/net/mctp/route.c +index 7a47a58aa54b4..6218dcd07e184 100644 +--- a/net/mctp/route.c ++++ b/net/mctp/route.c +@@ -663,7 +663,7 @@ struct mctp_sk_key *mctp_alloc_local_tag(struct mctp_sock *msk, + spin_unlock_irqrestore(&mns->keys_lock, flags); + + if (!tagbits) { +- kfree(key); ++ mctp_key_unref(key); + return ERR_PTR(-EBUSY); + } + +diff --git a/net/mptcp/diag.c b/net/mptcp/diag.c +index a536586742f28..6ff6f14674aa2 100644 +--- a/net/mptcp/diag.c ++++ b/net/mptcp/diag.c +@@ -13,17 +13,19 @@ + #include <uapi/linux/mptcp.h> + #include "protocol.h" + +-static int subflow_get_info(const struct sock *sk, struct sk_buff *skb) ++static int subflow_get_info(struct sock *sk, struct sk_buff *skb) + { + struct mptcp_subflow_context *sf; + struct nlattr *start; + u32 flags = 0; ++ bool slow; + int err; + + start = nla_nest_start_noflag(skb, INET_ULP_INFO_MPTCP); + if (!start) + return -EMSGSIZE; + ++ slow = lock_sock_fast(sk); + rcu_read_lock(); + sf = rcu_dereference(inet_csk(sk)->icsk_ulp_data); + if (!sf) { +@@ -63,17 +65,19 @@ static int subflow_get_info(const struct sock *sk, struct sk_buff *skb) + sf->map_data_len) || + nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_FLAGS, flags) || + nla_put_u8(skb, MPTCP_SUBFLOW_ATTR_ID_REM, sf->remote_id) || +- nla_put_u8(skb, MPTCP_SUBFLOW_ATTR_ID_LOC, sf->local_id)) { ++ nla_put_u8(skb, MPTCP_SUBFLOW_ATTR_ID_LOC, subflow_get_local_id(sf))) { + err = -EMSGSIZE; + goto nla_failure; + } + + rcu_read_unlock(); ++ unlock_sock_fast(sk, slow); + nla_nest_end(skb, start); + return 0; + + nla_failure: + rcu_read_unlock(); ++ unlock_sock_fast(sk, slow); + nla_nest_cancel(skb, start); + return err; + } +diff --git a/net/mptcp/fastopen.c b/net/mptcp/fastopen.c +index 74698582a2859..ad28da655f8bc 100644 +--- a/net/mptcp/fastopen.c ++++ b/net/mptcp/fastopen.c +@@ -59,13 +59,12 @@ void mptcp_fastopen_subflow_synack_set_params(struct mptcp_subflow_context *subf + mptcp_data_unlock(sk); + } + +-void mptcp_fastopen_gen_msk_ackseq(struct mptcp_sock *msk, struct mptcp_subflow_context *subflow, +- const struct mptcp_options_received *mp_opt) ++void __mptcp_fastopen_gen_msk_ackseq(struct mptcp_sock *msk, struct mptcp_subflow_context *subflow, ++ const struct mptcp_options_received *mp_opt) + { + struct sock *sk = (struct sock *)msk; + struct sk_buff *skb; + +- mptcp_data_lock(sk); + skb = skb_peek_tail(&sk->sk_receive_queue); + if (skb) { + WARN_ON_ONCE(MPTCP_SKB_CB(skb)->end_seq); +@@ -77,5 +76,4 @@ void mptcp_fastopen_gen_msk_ackseq(struct mptcp_sock *msk, struct mptcp_subflow_ + } + + pr_debug("msk=%p ack_seq=%llx", msk, msk->ack_seq); +- mptcp_data_unlock(sk); + } +diff --git a/net/mptcp/mib.c b/net/mptcp/mib.c +index a0990c365a2ea..c30405e768337 100644 +--- a/net/mptcp/mib.c ++++ b/net/mptcp/mib.c +@@ -66,6 +66,7 @@ static const struct snmp_mib mptcp_snmp_list[] = { + SNMP_MIB_ITEM("RcvWndShared", MPTCP_MIB_RCVWNDSHARED), + SNMP_MIB_ITEM("RcvWndConflictUpdate", MPTCP_MIB_RCVWNDCONFLICTUPDATE), + SNMP_MIB_ITEM("RcvWndConflict", MPTCP_MIB_RCVWNDCONFLICT), ++ SNMP_MIB_ITEM("MPCurrEstab", MPTCP_MIB_CURRESTAB), + SNMP_MIB_SENTINEL + }; + +diff --git a/net/mptcp/mib.h b/net/mptcp/mib.h +index cae71d9472529..dd7fd1f246b5f 100644 +--- a/net/mptcp/mib.h ++++ b/net/mptcp/mib.h +@@ -65,6 +65,7 @@ enum linux_mptcp_mib_field { + * conflict with another subflow while updating msk rcv wnd + */ + MPTCP_MIB_RCVWNDCONFLICT, /* Conflict with while updating msk rcv wnd */ ++ MPTCP_MIB_CURRESTAB, /* Current established MPTCP connections */ + __MPTCP_MIB_MAX + }; + +@@ -95,4 +96,11 @@ static inline void __MPTCP_INC_STATS(struct net *net, + __SNMP_INC_STATS(net->mib.mptcp_statistics, field); + } + ++static inline void MPTCP_DEC_STATS(struct net *net, ++ enum linux_mptcp_mib_field field) ++{ ++ if (likely(net->mib.mptcp_statistics)) ++ SNMP_DEC_STATS(net->mib.mptcp_statistics, field); ++} ++ + bool mptcp_mib_alloc(struct net *net); +diff --git a/net/mptcp/options.c b/net/mptcp/options.c +index d2527d189a799..e3e96a49f9229 100644 +--- a/net/mptcp/options.c ++++ b/net/mptcp/options.c +@@ -962,9 +962,7 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk, + /* subflows are fully established as soon as we get any + * additional ack, including ADD_ADDR. + */ +- subflow->fully_established = 1; +- WRITE_ONCE(msk->fully_established, true); +- goto check_notify; ++ goto set_fully_established; + } + + /* If the first established packet does not contain MP_CAPABLE + data +@@ -986,7 +984,10 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk, + set_fully_established: + if (unlikely(!READ_ONCE(msk->pm.server_side))) + pr_warn_once("bogus mpc option on established client sk"); +- mptcp_subflow_fully_established(subflow, mp_opt); ++ ++ mptcp_data_lock((struct sock *)msk); ++ __mptcp_subflow_fully_established(msk, subflow, mp_opt); ++ mptcp_data_unlock((struct sock *)msk); + + check_notify: + /* if the subflow is not already linked into the conn_list, we can't +diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c +index bf4d96f6f99a6..cccb720c1c685 100644 +--- a/net/mptcp/pm_netlink.c ++++ b/net/mptcp/pm_netlink.c +@@ -396,19 +396,6 @@ void mptcp_pm_free_anno_list(struct mptcp_sock *msk) + } + } + +-static bool lookup_address_in_vec(const struct mptcp_addr_info *addrs, unsigned int nr, +- const struct mptcp_addr_info *addr) +-{ +- int i; +- +- for (i = 0; i < nr; i++) { +- if (addrs[i].id == addr->id) +- return true; +- } +- +- return false; +-} +- + /* Fill all the remote addresses into the array addrs[], + * and return the array size. + */ +@@ -440,18 +427,34 @@ static unsigned int fill_remote_addresses_vec(struct mptcp_sock *msk, + msk->pm.subflows++; + addrs[i++] = remote; + } else { ++ DECLARE_BITMAP(unavail_id, MPTCP_PM_MAX_ADDR_ID + 1); ++ ++ /* Forbid creation of new subflows matching existing ++ * ones, possibly already created by incoming ADD_ADDR ++ */ ++ bitmap_zero(unavail_id, MPTCP_PM_MAX_ADDR_ID + 1); ++ mptcp_for_each_subflow(msk, subflow) ++ if (READ_ONCE(subflow->local_id) == local->id) ++ __set_bit(subflow->remote_id, unavail_id); ++ + mptcp_for_each_subflow(msk, subflow) { + ssk = mptcp_subflow_tcp_sock(subflow); + remote_address((struct sock_common *)ssk, &addrs[i]); +- addrs[i].id = subflow->remote_id; ++ addrs[i].id = READ_ONCE(subflow->remote_id); + if (deny_id0 && !addrs[i].id) + continue; + ++ if (test_bit(addrs[i].id, unavail_id)) ++ continue; ++ + if (!mptcp_pm_addr_families_match(sk, local, &addrs[i])) + continue; + +- if (!lookup_address_in_vec(addrs, i, &addrs[i]) && +- msk->pm.subflows < subflows_max) { ++ if (msk->pm.subflows < subflows_max) { ++ /* forbid creating multiple address towards ++ * this id ++ */ ++ __set_bit(addrs[i].id, unavail_id); + msk->pm.subflows++; + i++; + } +@@ -799,18 +802,18 @@ static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk, + + mptcp_for_each_subflow_safe(msk, subflow, tmp) { + struct sock *ssk = mptcp_subflow_tcp_sock(subflow); ++ u8 remote_id = READ_ONCE(subflow->remote_id); + int how = RCV_SHUTDOWN | SEND_SHUTDOWN; +- u8 id = subflow->local_id; ++ u8 id = subflow_get_local_id(subflow); + +- if (rm_type == MPTCP_MIB_RMADDR && subflow->remote_id != rm_id) ++ if (rm_type == MPTCP_MIB_RMADDR && remote_id != rm_id) + continue; + if (rm_type == MPTCP_MIB_RMSUBFLOW && !mptcp_local_id_match(msk, id, rm_id)) + continue; + + pr_debug(" -> %s rm_list_ids[%d]=%u local_id=%u remote_id=%u mpc_id=%u", + rm_type == MPTCP_MIB_RMADDR ? "address" : "subflow", +- i, rm_id, subflow->local_id, subflow->remote_id, +- msk->mpc_endpoint_id); ++ i, rm_id, id, remote_id, msk->mpc_endpoint_id); + spin_unlock_bh(&msk->pm.lock); + mptcp_subflow_shutdown(sk, ssk, how); + +@@ -901,7 +904,8 @@ static void __mptcp_pm_release_addr_entry(struct mptcp_pm_addr_entry *entry) + } + + static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet, +- struct mptcp_pm_addr_entry *entry) ++ struct mptcp_pm_addr_entry *entry, ++ bool needs_id) + { + struct mptcp_pm_addr_entry *cur, *del_entry = NULL; + unsigned int addr_max; +@@ -949,7 +953,7 @@ static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet, + } + } + +- if (!entry->addr.id) { ++ if (!entry->addr.id && needs_id) { + find_next: + entry->addr.id = find_next_zero_bit(pernet->id_bitmap, + MPTCP_PM_MAX_ADDR_ID + 1, +@@ -960,7 +964,7 @@ static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet, + } + } + +- if (!entry->addr.id) ++ if (!entry->addr.id && needs_id) + goto out; + + __set_bit(entry->addr.id, pernet->id_bitmap); +@@ -1048,6 +1052,11 @@ static int mptcp_pm_nl_create_listen_socket(struct sock *sk, + if (err) + return err; + ++ /* We don't use mptcp_set_state() here because it needs to be called ++ * under the msk socket lock. For the moment, that will not bring ++ * anything more than only calling inet_sk_state_store(), because the ++ * old status is known (TCP_CLOSE). ++ */ + inet_sk_state_store(newsk, TCP_LISTEN); + lock_sock(ssk); + err = __inet_listen_sk(ssk, backlog); +@@ -1087,7 +1096,7 @@ int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc + entry->ifindex = 0; + entry->flags = MPTCP_PM_ADDR_FLAG_IMPLICIT; + entry->lsk = NULL; +- ret = mptcp_pm_nl_append_new_local_addr(pernet, entry); ++ ret = mptcp_pm_nl_append_new_local_addr(pernet, entry, true); + if (ret < 0) + kfree(entry); + +@@ -1280,6 +1289,18 @@ static int mptcp_nl_add_subflow_or_signal_addr(struct net *net) + return 0; + } + ++static bool mptcp_pm_has_addr_attr_id(const struct nlattr *attr, ++ struct genl_info *info) ++{ ++ struct nlattr *tb[MPTCP_PM_ADDR_ATTR_MAX + 1]; ++ ++ if (!nla_parse_nested_deprecated(tb, MPTCP_PM_ADDR_ATTR_MAX, attr, ++ mptcp_pm_address_nl_policy, info->extack) && ++ tb[MPTCP_PM_ADDR_ATTR_ID]) ++ return true; ++ return false; ++} ++ + int mptcp_pm_nl_add_addr_doit(struct sk_buff *skb, struct genl_info *info) + { + struct nlattr *attr = info->attrs[MPTCP_PM_ENDPOINT_ADDR]; +@@ -1321,7 +1342,8 @@ int mptcp_pm_nl_add_addr_doit(struct sk_buff *skb, struct genl_info *info) + goto out_free; + } + } +- ret = mptcp_pm_nl_append_new_local_addr(pernet, entry); ++ ret = mptcp_pm_nl_append_new_local_addr(pernet, entry, ++ !mptcp_pm_has_addr_attr_id(attr, info)); + if (ret < 0) { + GENL_SET_ERR_MSG_FMT(info, "too many addresses or duplicate one: %d", ret); + goto out_free; +@@ -1975,7 +1997,7 @@ static int mptcp_event_add_subflow(struct sk_buff *skb, const struct sock *ssk) + if (WARN_ON_ONCE(!sf)) + return -EINVAL; + +- if (nla_put_u8(skb, MPTCP_ATTR_LOC_ID, sf->local_id)) ++ if (nla_put_u8(skb, MPTCP_ATTR_LOC_ID, subflow_get_local_id(sf))) + return -EMSGSIZE; + + if (nla_put_u8(skb, MPTCP_ATTR_REM_ID, sf->remote_id)) +diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c +index 80857ef3b90f5..01b3a8f2f0e9c 100644 +--- a/net/mptcp/pm_userspace.c ++++ b/net/mptcp/pm_userspace.c +@@ -26,7 +26,8 @@ void mptcp_free_local_addr_list(struct mptcp_sock *msk) + } + + static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk, +- struct mptcp_pm_addr_entry *entry) ++ struct mptcp_pm_addr_entry *entry, ++ bool needs_id) + { + DECLARE_BITMAP(id_bitmap, MPTCP_PM_MAX_ADDR_ID + 1); + struct mptcp_pm_addr_entry *match = NULL; +@@ -41,7 +42,7 @@ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk, + spin_lock_bh(&msk->pm.lock); + list_for_each_entry(e, &msk->pm.userspace_pm_local_addr_list, list) { + addr_match = mptcp_addresses_equal(&e->addr, &entry->addr, true); +- if (addr_match && entry->addr.id == 0) ++ if (addr_match && entry->addr.id == 0 && needs_id) + entry->addr.id = e->addr.id; + id_match = (e->addr.id == entry->addr.id); + if (addr_match && id_match) { +@@ -64,7 +65,7 @@ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk, + } + + *e = *entry; +- if (!e->addr.id) ++ if (!e->addr.id && needs_id) + e->addr.id = find_next_zero_bit(id_bitmap, + MPTCP_PM_MAX_ADDR_ID + 1, + 1); +@@ -153,7 +154,7 @@ int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk, + if (new_entry.addr.port == msk_sport) + new_entry.addr.port = 0; + +- return mptcp_userspace_pm_append_new_local_addr(msk, &new_entry); ++ return mptcp_userspace_pm_append_new_local_addr(msk, &new_entry, true); + } + + int mptcp_pm_nl_announce_doit(struct sk_buff *skb, struct genl_info *info) +@@ -198,7 +199,7 @@ int mptcp_pm_nl_announce_doit(struct sk_buff *skb, struct genl_info *info) + goto announce_err; + } + +- err = mptcp_userspace_pm_append_new_local_addr(msk, &addr_val); ++ err = mptcp_userspace_pm_append_new_local_addr(msk, &addr_val, false); + if (err < 0) { + GENL_SET_ERR_MSG(info, "did not match address and id"); + goto announce_err; +@@ -233,7 +234,7 @@ static int mptcp_userspace_pm_remove_id_zero_address(struct mptcp_sock *msk, + + lock_sock(sk); + mptcp_for_each_subflow(msk, subflow) { +- if (subflow->local_id == 0) { ++ if (READ_ONCE(subflow->local_id) == 0) { + has_id_0 = true; + break; + } +@@ -378,7 +379,7 @@ int mptcp_pm_nl_subflow_create_doit(struct sk_buff *skb, struct genl_info *info) + } + + local.addr = addr_l; +- err = mptcp_userspace_pm_append_new_local_addr(msk, &local); ++ err = mptcp_userspace_pm_append_new_local_addr(msk, &local, false); + if (err < 0) { + GENL_SET_ERR_MSG(info, "did not match address and id"); + goto create_err; +diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c +index 0b42ce7de45cc..5305f2ff0fd21 100644 +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@ -99,7 +99,7 @@ static int __mptcp_socket_create(struct mptcp_sock *msk) + subflow->subflow_id = msk->subflow_id++; + + /* This is the first subflow, always with id 0 */ +- subflow->local_id_valid = 1; ++ WRITE_ONCE(subflow->local_id, 0); + mptcp_sock_graft(msk->first, sk->sk_socket); + iput(SOCK_INODE(ssock)); + +@@ -443,11 +443,11 @@ static void mptcp_check_data_fin_ack(struct sock *sk) + + switch (sk->sk_state) { + case TCP_FIN_WAIT1: +- inet_sk_state_store(sk, TCP_FIN_WAIT2); ++ mptcp_set_state(sk, TCP_FIN_WAIT2); + break; + case TCP_CLOSING: + case TCP_LAST_ACK: +- inet_sk_state_store(sk, TCP_CLOSE); ++ mptcp_set_state(sk, TCP_CLOSE); + break; + } + +@@ -608,13 +608,13 @@ static bool mptcp_check_data_fin(struct sock *sk) + + switch (sk->sk_state) { + case TCP_ESTABLISHED: +- inet_sk_state_store(sk, TCP_CLOSE_WAIT); ++ mptcp_set_state(sk, TCP_CLOSE_WAIT); + break; + case TCP_FIN_WAIT1: +- inet_sk_state_store(sk, TCP_CLOSING); ++ mptcp_set_state(sk, TCP_CLOSING); + break; + case TCP_FIN_WAIT2: +- inet_sk_state_store(sk, TCP_CLOSE); ++ mptcp_set_state(sk, TCP_CLOSE); + break; + default: + /* Other states not expected */ +@@ -789,7 +789,7 @@ static bool __mptcp_subflow_error_report(struct sock *sk, struct sock *ssk) + */ + ssk_state = inet_sk_state_load(ssk); + if (ssk_state == TCP_CLOSE && !sock_flag(sk, SOCK_DEAD)) +- inet_sk_state_store(sk, ssk_state); ++ mptcp_set_state(sk, ssk_state); + WRITE_ONCE(sk->sk_err, -err); + + /* This barrier is coupled with smp_rmb() in mptcp_poll() */ +@@ -2480,7 +2480,7 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk, + inet_sk_state_load(msk->first) == TCP_CLOSE) { + if (sk->sk_state != TCP_ESTABLISHED || + msk->in_accept_queue || sock_flag(sk, SOCK_DEAD)) { +- inet_sk_state_store(sk, TCP_CLOSE); ++ mptcp_set_state(sk, TCP_CLOSE); + mptcp_close_wake_up(sk); + } else { + mptcp_start_tout_timer(sk); +@@ -2575,7 +2575,7 @@ static void mptcp_check_fastclose(struct mptcp_sock *msk) + WRITE_ONCE(sk->sk_err, ECONNRESET); + } + +- inet_sk_state_store(sk, TCP_CLOSE); ++ mptcp_set_state(sk, TCP_CLOSE); + WRITE_ONCE(sk->sk_shutdown, SHUTDOWN_MASK); + smp_mb__before_atomic(); /* SHUTDOWN must be visible first */ + set_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags); +@@ -2710,7 +2710,7 @@ static void mptcp_do_fastclose(struct sock *sk) + struct mptcp_subflow_context *subflow, *tmp; + struct mptcp_sock *msk = mptcp_sk(sk); + +- inet_sk_state_store(sk, TCP_CLOSE); ++ mptcp_set_state(sk, TCP_CLOSE); + mptcp_for_each_subflow_safe(msk, subflow, tmp) + __mptcp_close_ssk(sk, mptcp_subflow_tcp_sock(subflow), + subflow, MPTCP_CF_FASTCLOSE); +@@ -2888,6 +2888,24 @@ void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how) + release_sock(ssk); + } + ++void mptcp_set_state(struct sock *sk, int state) ++{ ++ int oldstate = sk->sk_state; ++ ++ switch (state) { ++ case TCP_ESTABLISHED: ++ if (oldstate != TCP_ESTABLISHED) ++ MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_CURRESTAB); ++ break; ++ ++ default: ++ if (oldstate == TCP_ESTABLISHED) ++ MPTCP_DEC_STATS(sock_net(sk), MPTCP_MIB_CURRESTAB); ++ } ++ ++ inet_sk_state_store(sk, state); ++} ++ + static const unsigned char new_state[16] = { + /* current state: new state: action: */ + [0 /* (Invalid) */] = TCP_CLOSE, +@@ -2910,7 +2928,7 @@ static int mptcp_close_state(struct sock *sk) + int next = (int)new_state[sk->sk_state]; + int ns = next & TCP_STATE_MASK; + +- inet_sk_state_store(sk, ns); ++ mptcp_set_state(sk, ns); + + return next & TCP_ACTION_FIN; + } +@@ -3021,7 +3039,7 @@ bool __mptcp_close(struct sock *sk, long timeout) + + if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) { + mptcp_check_listen_stop(sk); +- inet_sk_state_store(sk, TCP_CLOSE); ++ mptcp_set_state(sk, TCP_CLOSE); + goto cleanup; + } + +@@ -3064,7 +3082,7 @@ bool __mptcp_close(struct sock *sk, long timeout) + * state, let's not keep resources busy for no reasons + */ + if (subflows_alive == 0) +- inet_sk_state_store(sk, TCP_CLOSE); ++ mptcp_set_state(sk, TCP_CLOSE); + + sock_hold(sk); + pr_debug("msk=%p state=%d", sk, sk->sk_state); +@@ -3130,7 +3148,7 @@ static int mptcp_disconnect(struct sock *sk, int flags) + return -EBUSY; + + mptcp_check_listen_stop(sk); +- inet_sk_state_store(sk, TCP_CLOSE); ++ mptcp_set_state(sk, TCP_CLOSE); + + mptcp_stop_rtx_timer(sk); + mptcp_stop_tout_timer(sk); +@@ -3182,6 +3200,7 @@ struct sock *mptcp_sk_clone_init(const struct sock *sk, + { + struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req); + struct sock *nsk = sk_clone_lock(sk, GFP_ATOMIC); ++ struct mptcp_subflow_context *subflow; + struct mptcp_sock *msk; + + if (!nsk) +@@ -3218,11 +3237,12 @@ struct sock *mptcp_sk_clone_init(const struct sock *sk, + /* this can't race with mptcp_close(), as the msk is + * not yet exposted to user-space + */ +- inet_sk_state_store(nsk, TCP_ESTABLISHED); ++ mptcp_set_state(nsk, TCP_ESTABLISHED); + + /* The msk maintain a ref to each subflow in the connections list */ + WRITE_ONCE(msk->first, ssk); +- list_add(&mptcp_subflow_ctx(ssk)->node, &msk->conn_list); ++ subflow = mptcp_subflow_ctx(ssk); ++ list_add(&subflow->node, &msk->conn_list); + sock_hold(ssk); + + /* new mpc subflow takes ownership of the newly +@@ -3237,6 +3257,9 @@ struct sock *mptcp_sk_clone_init(const struct sock *sk, + __mptcp_propagate_sndbuf(nsk, ssk); + + mptcp_rcv_space_init(msk, ssk); ++ ++ if (mp_opt->suboptions & OPTION_MPTCP_MPC_ACK) ++ __mptcp_subflow_fully_established(msk, subflow, mp_opt); + bh_unlock_sock(nsk); + + /* note: the newly allocated socket refcount is 2 now */ +@@ -3512,10 +3535,6 @@ void mptcp_finish_connect(struct sock *ssk) + * accessing the field below + */ + WRITE_ONCE(msk->local_key, subflow->local_key); +- WRITE_ONCE(msk->write_seq, subflow->idsn + 1); +- WRITE_ONCE(msk->snd_nxt, msk->write_seq); +- WRITE_ONCE(msk->snd_una, msk->write_seq); +- WRITE_ONCE(msk->wnd_end, msk->snd_nxt + tcp_sk(ssk)->snd_wnd); + + mptcp_pm_new_connection(msk, ssk, 0); + } +@@ -3673,7 +3692,7 @@ static int mptcp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) + if (IS_ERR(ssk)) + return PTR_ERR(ssk); + +- inet_sk_state_store(sk, TCP_SYN_SENT); ++ mptcp_set_state(sk, TCP_SYN_SENT); + subflow = mptcp_subflow_ctx(ssk); + #ifdef CONFIG_TCP_MD5SIG + /* no MPTCP if MD5SIG is enabled on this socket or we may run out of +@@ -3723,7 +3742,7 @@ static int mptcp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) + if (unlikely(err)) { + /* avoid leaving a dangling token in an unconnected socket */ + mptcp_token_destroy(msk); +- inet_sk_state_store(sk, TCP_CLOSE); ++ mptcp_set_state(sk, TCP_CLOSE); + return err; + } + +@@ -3813,13 +3832,13 @@ static int mptcp_listen(struct socket *sock, int backlog) + goto unlock; + } + +- inet_sk_state_store(sk, TCP_LISTEN); ++ mptcp_set_state(sk, TCP_LISTEN); + sock_set_flag(sk, SOCK_RCU_FREE); + + lock_sock(ssk); + err = __inet_listen_sk(ssk, backlog); + release_sock(ssk); +- inet_sk_state_store(sk, inet_sk_state_load(ssk)); ++ mptcp_set_state(sk, inet_sk_state_load(ssk)); + + if (!err) { + sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); +@@ -3879,7 +3898,7 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock, + __mptcp_close_ssk(newsk, msk->first, + mptcp_subflow_ctx(msk->first), 0); + if (unlikely(list_is_singular(&msk->conn_list))) +- inet_sk_state_store(newsk, TCP_CLOSE); ++ mptcp_set_state(newsk, TCP_CLOSE); + } + } + release_sock(newsk); +diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h +index 27f3fedb9c366..3e50baba1b2a9 100644 +--- a/net/mptcp/protocol.h ++++ b/net/mptcp/protocol.h +@@ -491,10 +491,9 @@ struct mptcp_subflow_context { + remote_key_valid : 1, /* received the peer key from */ + disposable : 1, /* ctx can be free at ulp release time */ + stale : 1, /* unable to snd/rcv data, do not use for xmit */ +- local_id_valid : 1, /* local_id is correctly initialized */ + valid_csum_seen : 1, /* at least one csum validated */ + is_mptfo : 1, /* subflow is doing TFO */ +- __unused : 9; ++ __unused : 10; + bool data_avail; + bool scheduled; + u32 remote_nonce; +@@ -505,7 +504,7 @@ struct mptcp_subflow_context { + u8 hmac[MPTCPOPT_HMAC_LEN]; /* MPJ subflow only */ + u64 iasn; /* initial ack sequence number, MPC subflows only */ + }; +- u8 local_id; ++ s16 local_id; /* if negative not initialized yet */ + u8 remote_id; + u8 reset_seen:1; + u8 reset_transient:1; +@@ -556,6 +555,7 @@ mptcp_subflow_ctx_reset(struct mptcp_subflow_context *subflow) + { + memset(&subflow->reset, 0, sizeof(subflow->reset)); + subflow->request_mptcp = 1; ++ WRITE_ONCE(subflow->local_id, -1); + } + + static inline u64 +@@ -622,8 +622,9 @@ unsigned int mptcp_stale_loss_cnt(const struct net *net); + unsigned int mptcp_close_timeout(const struct sock *sk); + int mptcp_get_pm_type(const struct net *net); + const char *mptcp_get_scheduler(const struct net *net); +-void mptcp_subflow_fully_established(struct mptcp_subflow_context *subflow, +- const struct mptcp_options_received *mp_opt); ++void __mptcp_subflow_fully_established(struct mptcp_sock *msk, ++ struct mptcp_subflow_context *subflow, ++ const struct mptcp_options_received *mp_opt); + bool __mptcp_retransmit_pending_data(struct sock *sk); + void mptcp_check_and_set_pending(struct sock *sk); + void __mptcp_push_pending(struct sock *sk, unsigned int flags); +@@ -641,6 +642,7 @@ bool __mptcp_close(struct sock *sk, long timeout); + void mptcp_cancel_work(struct sock *sk); + void __mptcp_unaccepted_force_close(struct sock *sk); + void mptcp_set_owner_r(struct sk_buff *skb, struct sock *sk); ++void mptcp_set_state(struct sock *sk, int state); + + bool mptcp_addresses_equal(const struct mptcp_addr_info *a, + const struct mptcp_addr_info *b, bool use_port); +@@ -951,8 +953,8 @@ void mptcp_event_pm_listener(const struct sock *ssk, + enum mptcp_event_type event); + bool mptcp_userspace_pm_active(const struct mptcp_sock *msk); + +-void mptcp_fastopen_gen_msk_ackseq(struct mptcp_sock *msk, struct mptcp_subflow_context *subflow, +- const struct mptcp_options_received *mp_opt); ++void __mptcp_fastopen_gen_msk_ackseq(struct mptcp_sock *msk, struct mptcp_subflow_context *subflow, ++ const struct mptcp_options_received *mp_opt); + void mptcp_fastopen_subflow_synack_set_params(struct mptcp_subflow_context *subflow, + struct request_sock *req); + +@@ -1020,6 +1022,15 @@ int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc); + int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc); + int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc); + ++static inline u8 subflow_get_local_id(const struct mptcp_subflow_context *subflow) ++{ ++ int local_id = READ_ONCE(subflow->local_id); ++ ++ if (local_id < 0) ++ return 0; ++ return local_id; ++} ++ + void __init mptcp_pm_nl_init(void); + void mptcp_pm_nl_work(struct mptcp_sock *msk); + void mptcp_pm_nl_rm_subflow_received(struct mptcp_sock *msk, +diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c +index 5155ce5b71088..71ba86246ff89 100644 +--- a/net/mptcp/subflow.c ++++ b/net/mptcp/subflow.c +@@ -421,31 +421,26 @@ static bool subflow_use_different_dport(struct mptcp_sock *msk, const struct soc + + void __mptcp_sync_state(struct sock *sk, int state) + { ++ struct mptcp_subflow_context *subflow; + struct mptcp_sock *msk = mptcp_sk(sk); ++ struct sock *ssk = msk->first; + +- __mptcp_propagate_sndbuf(sk, msk->first); ++ subflow = mptcp_subflow_ctx(ssk); ++ __mptcp_propagate_sndbuf(sk, ssk); + if (!msk->rcvspace_init) +- mptcp_rcv_space_init(msk, msk->first); ++ mptcp_rcv_space_init(msk, ssk); ++ + if (sk->sk_state == TCP_SYN_SENT) { +- inet_sk_state_store(sk, state); ++ /* subflow->idsn is always available is TCP_SYN_SENT state, ++ * even for the FASTOPEN scenarios ++ */ ++ WRITE_ONCE(msk->write_seq, subflow->idsn + 1); ++ WRITE_ONCE(msk->snd_nxt, msk->write_seq); ++ mptcp_set_state(sk, state); + sk->sk_state_change(sk); + } + } + +-static void mptcp_propagate_state(struct sock *sk, struct sock *ssk) +-{ +- struct mptcp_sock *msk = mptcp_sk(sk); +- +- mptcp_data_lock(sk); +- if (!sock_owned_by_user(sk)) { +- __mptcp_sync_state(sk, ssk->sk_state); +- } else { +- msk->pending_state = ssk->sk_state; +- __set_bit(MPTCP_SYNC_STATE, &msk->cb_flags); +- } +- mptcp_data_unlock(sk); +-} +- + static void subflow_set_remote_key(struct mptcp_sock *msk, + struct mptcp_subflow_context *subflow, + const struct mptcp_options_received *mp_opt) +@@ -467,6 +462,31 @@ static void subflow_set_remote_key(struct mptcp_sock *msk, + atomic64_set(&msk->rcv_wnd_sent, subflow->iasn); + } + ++static void mptcp_propagate_state(struct sock *sk, struct sock *ssk, ++ struct mptcp_subflow_context *subflow, ++ const struct mptcp_options_received *mp_opt) ++{ ++ struct mptcp_sock *msk = mptcp_sk(sk); ++ ++ mptcp_data_lock(sk); ++ if (mp_opt) { ++ /* Options are available only in the non fallback cases ++ * avoid updating rx path fields otherwise ++ */ ++ WRITE_ONCE(msk->snd_una, subflow->idsn + 1); ++ WRITE_ONCE(msk->wnd_end, subflow->idsn + 1 + tcp_sk(ssk)->snd_wnd); ++ subflow_set_remote_key(msk, subflow, mp_opt); ++ } ++ ++ if (!sock_owned_by_user(sk)) { ++ __mptcp_sync_state(sk, ssk->sk_state); ++ } else { ++ msk->pending_state = ssk->sk_state; ++ __set_bit(MPTCP_SYNC_STATE, &msk->cb_flags); ++ } ++ mptcp_data_unlock(sk); ++} ++ + static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) + { + struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); +@@ -501,10 +521,9 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) + if (mp_opt.deny_join_id0) + WRITE_ONCE(msk->pm.remote_deny_join_id0, true); + subflow->mp_capable = 1; +- subflow_set_remote_key(msk, subflow, &mp_opt); + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPCAPABLEACTIVEACK); + mptcp_finish_connect(sk); +- mptcp_propagate_state(parent, sk); ++ mptcp_propagate_state(parent, sk, subflow, &mp_opt); + } else if (subflow->request_join) { + u8 hmac[SHA256_DIGEST_SIZE]; + +@@ -516,7 +535,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) + subflow->backup = mp_opt.backup; + subflow->thmac = mp_opt.thmac; + subflow->remote_nonce = mp_opt.nonce; +- subflow->remote_id = mp_opt.join_id; ++ WRITE_ONCE(subflow->remote_id, mp_opt.join_id); + pr_debug("subflow=%p, thmac=%llu, remote_nonce=%u backup=%d", + subflow, subflow->thmac, subflow->remote_nonce, + subflow->backup); +@@ -547,7 +566,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) + } + } else if (mptcp_check_fallback(sk)) { + fallback: +- mptcp_propagate_state(parent, sk); ++ mptcp_propagate_state(parent, sk, subflow, NULL); + } + return; + +@@ -558,8 +577,8 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) + + static void subflow_set_local_id(struct mptcp_subflow_context *subflow, int local_id) + { +- subflow->local_id = local_id; +- subflow->local_id_valid = 1; ++ WARN_ON_ONCE(local_id < 0 || local_id > 255); ++ WRITE_ONCE(subflow->local_id, local_id); + } + + static int subflow_chk_local_id(struct sock *sk) +@@ -568,7 +587,7 @@ static int subflow_chk_local_id(struct sock *sk) + struct mptcp_sock *msk = mptcp_sk(subflow->conn); + int err; + +- if (likely(subflow->local_id_valid)) ++ if (likely(subflow->local_id >= 0)) + return 0; + + err = mptcp_pm_get_local_id(msk, (struct sock_common *)sk); +@@ -732,17 +751,16 @@ void mptcp_subflow_drop_ctx(struct sock *ssk) + kfree_rcu(ctx, rcu); + } + +-void mptcp_subflow_fully_established(struct mptcp_subflow_context *subflow, +- const struct mptcp_options_received *mp_opt) ++void __mptcp_subflow_fully_established(struct mptcp_sock *msk, ++ struct mptcp_subflow_context *subflow, ++ const struct mptcp_options_received *mp_opt) + { +- struct mptcp_sock *msk = mptcp_sk(subflow->conn); +- + subflow_set_remote_key(msk, subflow, mp_opt); + subflow->fully_established = 1; + WRITE_ONCE(msk->fully_established, true); + + if (subflow->is_mptfo) +- mptcp_fastopen_gen_msk_ackseq(msk, subflow, mp_opt); ++ __mptcp_fastopen_gen_msk_ackseq(msk, subflow, mp_opt); + } + + static struct sock *subflow_syn_recv_sock(const struct sock *sk, +@@ -835,7 +853,6 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk, + * mpc option + */ + if (mp_opt.suboptions & OPTION_MPTCP_MPC_ACK) { +- mptcp_subflow_fully_established(ctx, &mp_opt); + mptcp_pm_fully_established(owner, child); + ctx->pm_notified = 1; + } +@@ -1550,7 +1567,7 @@ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc, + pr_debug("msk=%p remote_token=%u local_id=%d remote_id=%d", msk, + remote_token, local_id, remote_id); + subflow->remote_token = remote_token; +- subflow->remote_id = remote_id; ++ WRITE_ONCE(subflow->remote_id, remote_id); + subflow->request_join = 1; + subflow->request_bkup = !!(flags & MPTCP_PM_ADDR_FLAG_BACKUP); + subflow->subflow_id = msk->subflow_id++; +@@ -1714,6 +1731,7 @@ static struct mptcp_subflow_context *subflow_create_ctx(struct sock *sk, + pr_debug("subflow=%p", ctx); + + ctx->tcp_sock = sk; ++ WRITE_ONCE(ctx->local_id, -1); + + return ctx; + } +@@ -1747,7 +1765,7 @@ static void subflow_state_change(struct sock *sk) + mptcp_do_fallback(sk); + pr_fallback(msk); + subflow->conn_finished = 1; +- mptcp_propagate_state(parent, sk); ++ mptcp_propagate_state(parent, sk, subflow, NULL); + } + + /* as recvmsg() does not acquire the subflow socket for ssk selection +@@ -1949,14 +1967,14 @@ static void subflow_ulp_clone(const struct request_sock *req, + new_ctx->idsn = subflow_req->idsn; + + /* this is the first subflow, id is always 0 */ +- new_ctx->local_id_valid = 1; ++ subflow_set_local_id(new_ctx, 0); + } else if (subflow_req->mp_join) { + new_ctx->ssn_offset = subflow_req->ssn_offset; + new_ctx->mp_join = 1; + new_ctx->fully_established = 1; + new_ctx->remote_key_valid = 1; + new_ctx->backup = subflow_req->backup; +- new_ctx->remote_id = subflow_req->remote_id; ++ WRITE_ONCE(new_ctx->remote_id, subflow_req->remote_id); + new_ctx->token = subflow_req->token; + new_ctx->thmac = subflow_req->thmac; + +diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c +index c6bd533983c1f..4cc97f971264e 100644 +--- a/net/netfilter/nf_conntrack_proto_sctp.c ++++ b/net/netfilter/nf_conntrack_proto_sctp.c +@@ -283,7 +283,7 @@ sctp_new(struct nf_conn *ct, const struct sk_buff *skb, + pr_debug("Setting vtag %x for secondary conntrack\n", + sh->vtag); + ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = sh->vtag; +- } else { ++ } else if (sch->type == SCTP_CID_SHUTDOWN_ACK) { + /* If it is a shutdown ack OOTB packet, we expect a return + shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */ + pr_debug("Setting vtag %x for new conn OOTB\n", +diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c +index 920a5a29ae1dc..a0571339239c4 100644 +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -87,12 +87,22 @@ static u32 flow_offload_dst_cookie(struct flow_offload_tuple *flow_tuple) + return 0; + } + ++static struct dst_entry *nft_route_dst_fetch(struct nf_flow_route *route, ++ enum flow_offload_tuple_dir dir) ++{ ++ struct dst_entry *dst = route->tuple[dir].dst; ++ ++ route->tuple[dir].dst = NULL; ++ ++ return dst; ++} ++ + static int flow_offload_fill_route(struct flow_offload *flow, +- const struct nf_flow_route *route, ++ struct nf_flow_route *route, + enum flow_offload_tuple_dir dir) + { + struct flow_offload_tuple *flow_tuple = &flow->tuplehash[dir].tuple; +- struct dst_entry *dst = route->tuple[dir].dst; ++ struct dst_entry *dst = nft_route_dst_fetch(route, dir); + int i, j = 0; + + switch (flow_tuple->l3proto) { +@@ -122,6 +132,7 @@ static int flow_offload_fill_route(struct flow_offload *flow, + ETH_ALEN); + flow_tuple->out.ifidx = route->tuple[dir].out.ifindex; + flow_tuple->out.hw_ifidx = route->tuple[dir].out.hw_ifindex; ++ dst_release(dst); + break; + case FLOW_OFFLOAD_XMIT_XFRM: + case FLOW_OFFLOAD_XMIT_NEIGH: +@@ -146,7 +157,7 @@ static void nft_flow_dst_release(struct flow_offload *flow, + } + + void flow_offload_route_init(struct flow_offload *flow, +- const struct nf_flow_route *route) ++ struct nf_flow_route *route) + { + flow_offload_fill_route(flow, route, FLOW_OFFLOAD_DIR_ORIGINAL); + flow_offload_fill_route(flow, route, FLOW_OFFLOAD_DIR_REPLY); +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index 04c5aa4debc74..79e088e6f103e 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -684,15 +684,16 @@ static int nft_delobj(struct nft_ctx *ctx, struct nft_object *obj) + return err; + } + +-static int nft_trans_flowtable_add(struct nft_ctx *ctx, int msg_type, +- struct nft_flowtable *flowtable) ++static struct nft_trans * ++nft_trans_flowtable_add(struct nft_ctx *ctx, int msg_type, ++ struct nft_flowtable *flowtable) + { + struct nft_trans *trans; + + trans = nft_trans_alloc(ctx, msg_type, + sizeof(struct nft_trans_flowtable)); + if (trans == NULL) +- return -ENOMEM; ++ return ERR_PTR(-ENOMEM); + + if (msg_type == NFT_MSG_NEWFLOWTABLE) + nft_activate_next(ctx->net, flowtable); +@@ -701,22 +702,22 @@ static int nft_trans_flowtable_add(struct nft_ctx *ctx, int msg_type, + nft_trans_flowtable(trans) = flowtable; + nft_trans_commit_list_add_tail(ctx->net, trans); + +- return 0; ++ return trans; + } + + static int nft_delflowtable(struct nft_ctx *ctx, + struct nft_flowtable *flowtable) + { +- int err; ++ struct nft_trans *trans; + +- err = nft_trans_flowtable_add(ctx, NFT_MSG_DELFLOWTABLE, flowtable); +- if (err < 0) +- return err; ++ trans = nft_trans_flowtable_add(ctx, NFT_MSG_DELFLOWTABLE, flowtable); ++ if (IS_ERR(trans)) ++ return PTR_ERR(trans); + + nft_deactivate_next(ctx->net, flowtable); + nft_use_dec(&ctx->table->use); + +- return err; ++ return 0; + } + + static void __nft_reg_track_clobber(struct nft_regs_track *track, u8 dreg) +@@ -1251,6 +1252,7 @@ static int nf_tables_updtable(struct nft_ctx *ctx) + return 0; + + err_register_hooks: ++ ctx->table->flags |= NFT_TABLE_F_DORMANT; + nft_trans_destroy(trans); + return ret; + } +@@ -2080,7 +2082,7 @@ static struct nft_hook *nft_netdev_hook_alloc(struct net *net, + struct nft_hook *hook; + int err; + +- hook = kmalloc(sizeof(struct nft_hook), GFP_KERNEL_ACCOUNT); ++ hook = kzalloc(sizeof(struct nft_hook), GFP_KERNEL_ACCOUNT); + if (!hook) { + err = -ENOMEM; + goto err_hook_alloc; +@@ -2503,19 +2505,15 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, + RCU_INIT_POINTER(chain->blob_gen_0, blob); + RCU_INIT_POINTER(chain->blob_gen_1, blob); + +- err = nf_tables_register_hook(net, table, chain); +- if (err < 0) +- goto err_destroy_chain; +- + if (!nft_use_inc(&table->use)) { + err = -EMFILE; +- goto err_use; ++ goto err_destroy_chain; + } + + trans = nft_trans_chain_add(ctx, NFT_MSG_NEWCHAIN); + if (IS_ERR(trans)) { + err = PTR_ERR(trans); +- goto err_unregister_hook; ++ goto err_trans; + } + + nft_trans_chain_policy(trans) = NFT_CHAIN_POLICY_UNSET; +@@ -2523,17 +2521,22 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, + nft_trans_chain_policy(trans) = policy; + + err = nft_chain_add(table, chain); +- if (err < 0) { +- nft_trans_destroy(trans); +- goto err_unregister_hook; +- } ++ if (err < 0) ++ goto err_chain_add; ++ ++ /* This must be LAST to ensure no packets are walking over this chain. */ ++ err = nf_tables_register_hook(net, table, chain); ++ if (err < 0) ++ goto err_register_hook; + + return 0; + +-err_unregister_hook: ++err_register_hook: ++ nft_chain_del(chain); ++err_chain_add: ++ nft_trans_destroy(trans); ++err_trans: + nft_use_dec_restore(&table->use); +-err_use: +- nf_tables_unregister_hook(net, table, chain); + err_destroy_chain: + nf_tables_chain_destroy(ctx); + +@@ -8372,9 +8375,9 @@ static int nf_tables_newflowtable(struct sk_buff *skb, + u8 family = info->nfmsg->nfgen_family; + const struct nf_flowtable_type *type; + struct nft_flowtable *flowtable; +- struct nft_hook *hook, *next; + struct net *net = info->net; + struct nft_table *table; ++ struct nft_trans *trans; + struct nft_ctx ctx; + int err; + +@@ -8454,34 +8457,34 @@ static int nf_tables_newflowtable(struct sk_buff *skb, + err = nft_flowtable_parse_hook(&ctx, nla, &flowtable_hook, flowtable, + extack, true); + if (err < 0) +- goto err4; ++ goto err_flowtable_parse_hooks; + + list_splice(&flowtable_hook.list, &flowtable->hook_list); + flowtable->data.priority = flowtable_hook.priority; + flowtable->hooknum = flowtable_hook.num; + ++ trans = nft_trans_flowtable_add(&ctx, NFT_MSG_NEWFLOWTABLE, flowtable); ++ if (IS_ERR(trans)) { ++ err = PTR_ERR(trans); ++ goto err_flowtable_trans; ++ } ++ ++ /* This must be LAST to ensure no packets are walking over this flowtable. */ + err = nft_register_flowtable_net_hooks(ctx.net, table, + &flowtable->hook_list, + flowtable); +- if (err < 0) { +- nft_hooks_destroy(&flowtable->hook_list); +- goto err4; +- } +- +- err = nft_trans_flowtable_add(&ctx, NFT_MSG_NEWFLOWTABLE, flowtable); + if (err < 0) +- goto err5; ++ goto err_flowtable_hooks; + + list_add_tail_rcu(&flowtable->list, &table->flowtables); + + return 0; +-err5: +- list_for_each_entry_safe(hook, next, &flowtable->hook_list, list) { +- nft_unregister_flowtable_hook(net, flowtable, hook); +- list_del_rcu(&hook->list); +- kfree_rcu(hook, rcu); +- } +-err4: ++ ++err_flowtable_hooks: ++ nft_trans_destroy(trans); ++err_flowtable_trans: ++ nft_hooks_destroy(&flowtable->hook_list); ++err_flowtable_parse_hooks: + flowtable->data.type->free(&flowtable->data); + err3: + module_put(type->owner); +diff --git a/net/phonet/datagram.c b/net/phonet/datagram.c +index 3aa50dc7535b7..976fe250b5095 100644 +--- a/net/phonet/datagram.c ++++ b/net/phonet/datagram.c +@@ -34,10 +34,10 @@ static int pn_ioctl(struct sock *sk, int cmd, int *karg) + + switch (cmd) { + case SIOCINQ: +- lock_sock(sk); ++ spin_lock_bh(&sk->sk_receive_queue.lock); + skb = skb_peek(&sk->sk_receive_queue); + *karg = skb ? skb->len : 0; +- release_sock(sk); ++ spin_unlock_bh(&sk->sk_receive_queue.lock); + return 0; + + case SIOCPNADDRESOURCE: +diff --git a/net/phonet/pep.c b/net/phonet/pep.c +index faba31f2eff29..3dd5f52bc1b58 100644 +--- a/net/phonet/pep.c ++++ b/net/phonet/pep.c +@@ -917,6 +917,37 @@ static int pep_sock_enable(struct sock *sk, struct sockaddr *addr, int len) + return 0; + } + ++static unsigned int pep_first_packet_length(struct sock *sk) ++{ ++ struct pep_sock *pn = pep_sk(sk); ++ struct sk_buff_head *q; ++ struct sk_buff *skb; ++ unsigned int len = 0; ++ bool found = false; ++ ++ if (sock_flag(sk, SOCK_URGINLINE)) { ++ q = &pn->ctrlreq_queue; ++ spin_lock_bh(&q->lock); ++ skb = skb_peek(q); ++ if (skb) { ++ len = skb->len; ++ found = true; ++ } ++ spin_unlock_bh(&q->lock); ++ } ++ ++ if (likely(!found)) { ++ q = &sk->sk_receive_queue; ++ spin_lock_bh(&q->lock); ++ skb = skb_peek(q); ++ if (skb) ++ len = skb->len; ++ spin_unlock_bh(&q->lock); ++ } ++ ++ return len; ++} ++ + static int pep_ioctl(struct sock *sk, int cmd, int *karg) + { + struct pep_sock *pn = pep_sk(sk); +@@ -929,15 +960,7 @@ static int pep_ioctl(struct sock *sk, int cmd, int *karg) + break; + } + +- lock_sock(sk); +- if (sock_flag(sk, SOCK_URGINLINE) && +- !skb_queue_empty(&pn->ctrlreq_queue)) +- *karg = skb_peek(&pn->ctrlreq_queue)->len; +- else if (!skb_queue_empty(&sk->sk_receive_queue)) +- *karg = skb_peek(&sk->sk_receive_queue)->len; +- else +- *karg = 0; +- release_sock(sk); ++ *karg = pep_first_packet_length(sk); + ret = 0; + break; + +diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c +index 0a711c184c29b..674f7ae356ca2 100644 +--- a/net/sched/act_mirred.c ++++ b/net/sched/act_mirred.c +@@ -206,18 +206,14 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, + return err; + } + +-static bool is_mirred_nested(void) +-{ +- return unlikely(__this_cpu_read(mirred_nest_level) > 1); +-} +- +-static int tcf_mirred_forward(bool want_ingress, struct sk_buff *skb) ++static int ++tcf_mirred_forward(bool at_ingress, bool want_ingress, struct sk_buff *skb) + { + int err; + + if (!want_ingress) + err = tcf_dev_queue_xmit(skb, dev_queue_xmit); +- else if (is_mirred_nested()) ++ else if (!at_ingress) + err = netif_rx(skb); + else + err = netif_receive_skb(skb); +@@ -225,110 +221,123 @@ static int tcf_mirred_forward(bool want_ingress, struct sk_buff *skb) + return err; + } + +-TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb, +- const struct tc_action *a, +- struct tcf_result *res) ++static int tcf_mirred_to_dev(struct sk_buff *skb, struct tcf_mirred *m, ++ struct net_device *dev, ++ const bool m_mac_header_xmit, int m_eaction, ++ int retval) + { +- struct tcf_mirred *m = to_mirred(a); +- struct sk_buff *skb2 = skb; +- bool m_mac_header_xmit; +- struct net_device *dev; +- unsigned int nest_level; +- int retval, err = 0; +- bool use_reinsert; ++ struct sk_buff *skb_to_send = skb; + bool want_ingress; + bool is_redirect; + bool expects_nh; + bool at_ingress; +- int m_eaction; ++ bool dont_clone; + int mac_len; + bool at_nh; ++ int err; + +- nest_level = __this_cpu_inc_return(mirred_nest_level); +- if (unlikely(nest_level > MIRRED_NEST_LIMIT)) { +- net_warn_ratelimited("Packet exceeded mirred recursion limit on dev %s\n", +- netdev_name(skb->dev)); +- __this_cpu_dec(mirred_nest_level); +- return TC_ACT_SHOT; +- } +- +- tcf_lastuse_update(&m->tcf_tm); +- tcf_action_update_bstats(&m->common, skb); +- +- m_mac_header_xmit = READ_ONCE(m->tcfm_mac_header_xmit); +- m_eaction = READ_ONCE(m->tcfm_eaction); +- retval = READ_ONCE(m->tcf_action); +- dev = rcu_dereference_bh(m->tcfm_dev); +- if (unlikely(!dev)) { +- pr_notice_once("tc mirred: target device is gone\n"); +- goto out; +- } +- ++ is_redirect = tcf_mirred_is_act_redirect(m_eaction); + if (unlikely(!(dev->flags & IFF_UP)) || !netif_carrier_ok(dev)) { + net_notice_ratelimited("tc mirred to Houston: device %s is down\n", + dev->name); +- goto out; ++ goto err_cant_do; + } + + /* we could easily avoid the clone only if called by ingress and clsact; + * since we can't easily detect the clsact caller, skip clone only for + * ingress - that covers the TC S/W datapath. + */ +- is_redirect = tcf_mirred_is_act_redirect(m_eaction); + at_ingress = skb_at_tc_ingress(skb); +- use_reinsert = at_ingress && is_redirect && +- tcf_mirred_can_reinsert(retval); +- if (!use_reinsert) { +- skb2 = skb_clone(skb, GFP_ATOMIC); +- if (!skb2) +- goto out; ++ dont_clone = skb_at_tc_ingress(skb) && is_redirect && ++ tcf_mirred_can_reinsert(retval); ++ if (!dont_clone) { ++ skb_to_send = skb_clone(skb, GFP_ATOMIC); ++ if (!skb_to_send) ++ goto err_cant_do; + } + + want_ingress = tcf_mirred_act_wants_ingress(m_eaction); + + /* All mirred/redirected skbs should clear previous ct info */ +- nf_reset_ct(skb2); ++ nf_reset_ct(skb_to_send); + if (want_ingress && !at_ingress) /* drop dst for egress -> ingress */ +- skb_dst_drop(skb2); ++ skb_dst_drop(skb_to_send); + + expects_nh = want_ingress || !m_mac_header_xmit; + at_nh = skb->data == skb_network_header(skb); + if (at_nh != expects_nh) { +- mac_len = skb_at_tc_ingress(skb) ? skb->mac_len : ++ mac_len = at_ingress ? skb->mac_len : + skb_network_offset(skb); + if (expects_nh) { + /* target device/action expect data at nh */ +- skb_pull_rcsum(skb2, mac_len); ++ skb_pull_rcsum(skb_to_send, mac_len); + } else { + /* target device/action expect data at mac */ +- skb_push_rcsum(skb2, mac_len); ++ skb_push_rcsum(skb_to_send, mac_len); + } + } + +- skb2->skb_iif = skb->dev->ifindex; +- skb2->dev = dev; ++ skb_to_send->skb_iif = skb->dev->ifindex; ++ skb_to_send->dev = dev; + +- /* mirror is always swallowed */ + if (is_redirect) { +- skb_set_redirected(skb2, skb2->tc_at_ingress); +- +- /* let's the caller reinsert the packet, if possible */ +- if (use_reinsert) { +- err = tcf_mirred_forward(want_ingress, skb); +- if (err) +- tcf_action_inc_overlimit_qstats(&m->common); +- __this_cpu_dec(mirred_nest_level); +- return TC_ACT_CONSUMED; +- } ++ if (skb == skb_to_send) ++ retval = TC_ACT_CONSUMED; ++ ++ skb_set_redirected(skb_to_send, skb_to_send->tc_at_ingress); ++ ++ err = tcf_mirred_forward(at_ingress, want_ingress, skb_to_send); ++ } else { ++ err = tcf_mirred_forward(at_ingress, want_ingress, skb_to_send); + } ++ if (err) ++ tcf_action_inc_overlimit_qstats(&m->common); ++ ++ return retval; ++ ++err_cant_do: ++ if (is_redirect) ++ retval = TC_ACT_SHOT; ++ tcf_action_inc_overlimit_qstats(&m->common); ++ return retval; ++} ++ ++TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb, ++ const struct tc_action *a, ++ struct tcf_result *res) ++{ ++ struct tcf_mirred *m = to_mirred(a); ++ int retval = READ_ONCE(m->tcf_action); ++ unsigned int nest_level; ++ bool m_mac_header_xmit; ++ struct net_device *dev; ++ int m_eaction; + +- err = tcf_mirred_forward(want_ingress, skb2); +- if (err) { +-out: ++ nest_level = __this_cpu_inc_return(mirred_nest_level); ++ if (unlikely(nest_level > MIRRED_NEST_LIMIT)) { ++ net_warn_ratelimited("Packet exceeded mirred recursion limit on dev %s\n", ++ netdev_name(skb->dev)); ++ retval = TC_ACT_SHOT; ++ goto dec_nest_level; ++ } ++ ++ tcf_lastuse_update(&m->tcf_tm); ++ tcf_action_update_bstats(&m->common, skb); ++ ++ dev = rcu_dereference_bh(m->tcfm_dev); ++ if (unlikely(!dev)) { ++ pr_notice_once("tc mirred: target device is gone\n"); + tcf_action_inc_overlimit_qstats(&m->common); +- if (tcf_mirred_is_act_redirect(m_eaction)) +- retval = TC_ACT_SHOT; ++ goto dec_nest_level; + } ++ ++ m_mac_header_xmit = READ_ONCE(m->tcfm_mac_header_xmit); ++ m_eaction = READ_ONCE(m->tcfm_eaction); ++ ++ retval = tcf_mirred_to_dev(skb, m, dev, m_mac_header_xmit, m_eaction, ++ retval); ++ ++dec_nest_level: + __this_cpu_dec(mirred_nest_level); + + return retval; +diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c +index efb9d2811b73d..6ee7064c82fcc 100644 +--- a/net/sched/cls_flower.c ++++ b/net/sched/cls_flower.c +@@ -2460,8 +2460,11 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, + } + + errout_idr: +- if (!fold) ++ if (!fold) { ++ spin_lock(&tp->lock); + idr_remove(&head->handle_idr, fnew->handle); ++ spin_unlock(&tp->lock); ++ } + __fl_put(fnew); + errout_tb: + kfree(tb); +diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c +index 5b045284849e0..c9189a970eec3 100644 +--- a/net/switchdev/switchdev.c ++++ b/net/switchdev/switchdev.c +@@ -19,6 +19,35 @@ + #include <linux/rtnetlink.h> + #include <net/switchdev.h> + ++static bool switchdev_obj_eq(const struct switchdev_obj *a, ++ const struct switchdev_obj *b) ++{ ++ const struct switchdev_obj_port_vlan *va, *vb; ++ const struct switchdev_obj_port_mdb *ma, *mb; ++ ++ if (a->id != b->id || a->orig_dev != b->orig_dev) ++ return false; ++ ++ switch (a->id) { ++ case SWITCHDEV_OBJ_ID_PORT_VLAN: ++ va = SWITCHDEV_OBJ_PORT_VLAN(a); ++ vb = SWITCHDEV_OBJ_PORT_VLAN(b); ++ return va->flags == vb->flags && ++ va->vid == vb->vid && ++ va->changed == vb->changed; ++ case SWITCHDEV_OBJ_ID_PORT_MDB: ++ case SWITCHDEV_OBJ_ID_HOST_MDB: ++ ma = SWITCHDEV_OBJ_PORT_MDB(a); ++ mb = SWITCHDEV_OBJ_PORT_MDB(b); ++ return ma->vid == mb->vid && ++ ether_addr_equal(ma->addr, mb->addr); ++ default: ++ break; ++ } ++ ++ BUG(); ++} ++ + static LIST_HEAD(deferred); + static DEFINE_SPINLOCK(deferred_lock); + +@@ -307,6 +336,50 @@ int switchdev_port_obj_del(struct net_device *dev, + } + EXPORT_SYMBOL_GPL(switchdev_port_obj_del); + ++/** ++ * switchdev_port_obj_act_is_deferred - Is object action pending? ++ * ++ * @dev: port device ++ * @nt: type of action; add or delete ++ * @obj: object to test ++ * ++ * Returns true if a deferred item is pending, which is ++ * equivalent to the action @nt on an object @obj. ++ * ++ * rtnl_lock must be held. ++ */ ++bool switchdev_port_obj_act_is_deferred(struct net_device *dev, ++ enum switchdev_notifier_type nt, ++ const struct switchdev_obj *obj) ++{ ++ struct switchdev_deferred_item *dfitem; ++ bool found = false; ++ ++ ASSERT_RTNL(); ++ ++ spin_lock_bh(&deferred_lock); ++ ++ list_for_each_entry(dfitem, &deferred, list) { ++ if (dfitem->dev != dev) ++ continue; ++ ++ if ((dfitem->func == switchdev_port_obj_add_deferred && ++ nt == SWITCHDEV_PORT_OBJ_ADD) || ++ (dfitem->func == switchdev_port_obj_del_deferred && ++ nt == SWITCHDEV_PORT_OBJ_DEL)) { ++ if (switchdev_obj_eq((const void *)dfitem->data, obj)) { ++ found = true; ++ break; ++ } ++ } ++ } ++ ++ spin_unlock_bh(&deferred_lock); ++ ++ return found; ++} ++EXPORT_SYMBOL_GPL(switchdev_port_obj_act_is_deferred); ++ + static ATOMIC_NOTIFIER_HEAD(switchdev_notif_chain); + static BLOCKING_NOTIFIER_HEAD(switchdev_blocking_notif_chain); + +diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c +index 1c2c6800949dd..b4674f03d71a9 100644 +--- a/net/tls/tls_main.c ++++ b/net/tls/tls_main.c +@@ -1003,7 +1003,7 @@ static u16 tls_user_config(struct tls_context *ctx, bool tx) + return 0; + } + +-static int tls_get_info(const struct sock *sk, struct sk_buff *skb) ++static int tls_get_info(struct sock *sk, struct sk_buff *skb) + { + u16 version, cipher_type; + struct tls_context *ctx; +diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c +index 9fbc70200cd0f..de96959336c48 100644 +--- a/net/tls/tls_sw.c ++++ b/net/tls/tls_sw.c +@@ -1772,7 +1772,8 @@ static int process_rx_list(struct tls_sw_context_rx *ctx, + u8 *control, + size_t skip, + size_t len, +- bool is_peek) ++ bool is_peek, ++ bool *more) + { + struct sk_buff *skb = skb_peek(&ctx->rx_list); + struct tls_msg *tlm; +@@ -1785,7 +1786,7 @@ static int process_rx_list(struct tls_sw_context_rx *ctx, + + err = tls_record_content_type(msg, tlm, control); + if (err <= 0) +- goto out; ++ goto more; + + if (skip < rxm->full_len) + break; +@@ -1803,12 +1804,12 @@ static int process_rx_list(struct tls_sw_context_rx *ctx, + + err = tls_record_content_type(msg, tlm, control); + if (err <= 0) +- goto out; ++ goto more; + + err = skb_copy_datagram_msg(skb, rxm->offset + skip, + msg, chunk); + if (err < 0) +- goto out; ++ goto more; + + len = len - chunk; + copied = copied + chunk; +@@ -1844,6 +1845,10 @@ static int process_rx_list(struct tls_sw_context_rx *ctx, + + out: + return copied ? : err; ++more: ++ if (more) ++ *more = true; ++ goto out; + } + + static bool +@@ -1947,6 +1952,7 @@ int tls_sw_recvmsg(struct sock *sk, + int target, err; + bool is_kvec = iov_iter_is_kvec(&msg->msg_iter); + bool is_peek = flags & MSG_PEEK; ++ bool rx_more = false; + bool released = true; + bool bpf_strp_enabled; + bool zc_capable; +@@ -1966,12 +1972,12 @@ int tls_sw_recvmsg(struct sock *sk, + goto end; + + /* Process pending decrypted records. It must be non-zero-copy */ +- err = process_rx_list(ctx, msg, &control, 0, len, is_peek); ++ err = process_rx_list(ctx, msg, &control, 0, len, is_peek, &rx_more); + if (err < 0) + goto end; + + copied = err; +- if (len <= copied) ++ if (len <= copied || (copied && control != TLS_RECORD_TYPE_DATA) || rx_more) + goto end; + + target = sock_rcvlowat(sk, flags & MSG_WAITALL, len); +@@ -2064,6 +2070,8 @@ int tls_sw_recvmsg(struct sock *sk, + decrypted += chunk; + len -= chunk; + __skb_queue_tail(&ctx->rx_list, skb); ++ if (unlikely(control != TLS_RECORD_TYPE_DATA)) ++ break; + continue; + } + +@@ -2128,10 +2136,10 @@ int tls_sw_recvmsg(struct sock *sk, + /* Drain records from the rx_list & copy if required */ + if (is_peek || is_kvec) + err = process_rx_list(ctx, msg, &control, copied, +- decrypted, is_peek); ++ decrypted, is_peek, NULL); + else + err = process_rx_list(ctx, msg, &control, 0, +- async_copy_bytes, is_peek); ++ async_copy_bytes, is_peek, NULL); + } + + copied += decrypted; +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index 30b178ebba60a..0748e7ea5210e 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -782,19 +782,6 @@ static int unix_seqpacket_sendmsg(struct socket *, struct msghdr *, size_t); + static int unix_seqpacket_recvmsg(struct socket *, struct msghdr *, size_t, + int); + +-static int unix_set_peek_off(struct sock *sk, int val) +-{ +- struct unix_sock *u = unix_sk(sk); +- +- if (mutex_lock_interruptible(&u->iolock)) +- return -EINTR; +- +- WRITE_ONCE(sk->sk_peek_off, val); +- mutex_unlock(&u->iolock); +- +- return 0; +-} +- + #ifdef CONFIG_PROC_FS + static int unix_count_nr_fds(struct sock *sk) + { +@@ -862,7 +849,7 @@ static const struct proto_ops unix_stream_ops = { + .read_skb = unix_stream_read_skb, + .mmap = sock_no_mmap, + .splice_read = unix_stream_splice_read, +- .set_peek_off = unix_set_peek_off, ++ .set_peek_off = sk_set_peek_off, + .show_fdinfo = unix_show_fdinfo, + }; + +@@ -886,7 +873,7 @@ static const struct proto_ops unix_dgram_ops = { + .read_skb = unix_read_skb, + .recvmsg = unix_dgram_recvmsg, + .mmap = sock_no_mmap, +- .set_peek_off = unix_set_peek_off, ++ .set_peek_off = sk_set_peek_off, + .show_fdinfo = unix_show_fdinfo, + }; + +@@ -909,7 +896,7 @@ static const struct proto_ops unix_seqpacket_ops = { + .sendmsg = unix_seqpacket_sendmsg, + .recvmsg = unix_seqpacket_recvmsg, + .mmap = sock_no_mmap, +- .set_peek_off = unix_set_peek_off, ++ .set_peek_off = sk_set_peek_off, + .show_fdinfo = unix_show_fdinfo, + }; + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 1cbbb11ea5033..fbf95b7ff6b43 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -4008,6 +4008,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * + } + wiphy_unlock(&rdev->wiphy); + ++ if_start = 0; + wp_idx++; + } + out: +diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c +index 688e641cd2784..da1582de6e84a 100644 +--- a/net/xdp/xsk.c ++++ b/net/xdp/xsk.c +@@ -711,7 +711,8 @@ static struct sk_buff *xsk_build_skb(struct xdp_sock *xs, + memcpy(vaddr, buffer, len); + kunmap_local(vaddr); + +- skb_add_rx_frag(skb, nr_frags, page, 0, len, 0); ++ skb_add_rx_frag(skb, nr_frags, page, 0, len, PAGE_SIZE); ++ refcount_add(PAGE_SIZE, &xs->sk.sk_wmem_alloc); + } + } + +diff --git a/scripts/bpf_doc.py b/scripts/bpf_doc.py +index 61b7dddedc461..0669bac5e900e 100755 +--- a/scripts/bpf_doc.py ++++ b/scripts/bpf_doc.py +@@ -513,7 +513,7 @@ eBPF programs can have an associated license, passed along with the bytecode + instructions to the kernel when the programs are loaded. The format for that + string is identical to the one in use for kernel modules (Dual licenses, such + as "Dual BSD/GPL", may be used). Some helper functions are only accessible to +-programs that are compatible with the GNU Privacy License (GPL). ++programs that are compatible with the GNU General Public License (GNU GPL). + + In order to use such helpers, the eBPF program must be loaded with the correct + license string passed (via **attr**) to the **bpf**\\ () system call, and this +diff --git a/sound/pci/hda/cs35l41_hda_property.c b/sound/pci/hda/cs35l41_hda_property.c +index 35277ce890a46..d74cf11eef1ea 100644 +--- a/sound/pci/hda/cs35l41_hda_property.c ++++ b/sound/pci/hda/cs35l41_hda_property.c +@@ -76,6 +76,8 @@ static const struct cs35l41_config cs35l41_config_table[] = { + { "10431533", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, + { "10431573", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, + { "10431663", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 1000, 4500, 24 }, ++ { "10431683", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 }, ++ { "104316A3", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, + { "104316D3", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, + { "104316F3", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, + { "104317F3", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, +@@ -410,6 +412,8 @@ static const struct cs35l41_prop_model cs35l41_prop_model_table[] = { + { "CSC3551", "10431533", generic_dsd_config }, + { "CSC3551", "10431573", generic_dsd_config }, + { "CSC3551", "10431663", generic_dsd_config }, ++ { "CSC3551", "10431683", generic_dsd_config }, ++ { "CSC3551", "104316A3", generic_dsd_config }, + { "CSC3551", "104316D3", generic_dsd_config }, + { "CSC3551", "104316F3", generic_dsd_config }, + { "CSC3551", "104317F3", generic_dsd_config }, +diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c +index 2276adc844784..1b550c42db092 100644 +--- a/sound/pci/hda/hda_intel.c ++++ b/sound/pci/hda/hda_intel.c +@@ -1729,9 +1729,11 @@ static int default_bdl_pos_adj(struct azx *chip) + /* some exceptions: Atoms seem problematic with value 1 */ + if (chip->pci->vendor == PCI_VENDOR_ID_INTEL) { + switch (chip->pci->device) { +- case 0x0f04: /* Baytrail */ +- case 0x2284: /* Braswell */ ++ case PCI_DEVICE_ID_INTEL_HDA_BYT: ++ case PCI_DEVICE_ID_INTEL_HDA_BSW: + return 32; ++ case PCI_DEVICE_ID_INTEL_HDA_APL: ++ return 64; + } + } + +diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c +index 34b14f2611ba8..12ff0a558ea8f 100644 +--- a/sound/soc/amd/acp/acp-mach-common.c ++++ b/sound/soc/amd/acp/acp-mach-common.c +@@ -1428,8 +1428,13 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card) + if (drv_data->amp_cpu_id == I2S_SP) { + links[i].name = "acp-amp-codec"; + links[i].id = AMP_BE_ID; +- links[i].cpus = sof_sp_virtual; +- links[i].num_cpus = ARRAY_SIZE(sof_sp_virtual); ++ if (drv_data->platform == RENOIR) { ++ links[i].cpus = sof_sp; ++ links[i].num_cpus = ARRAY_SIZE(sof_sp); ++ } else { ++ links[i].cpus = sof_sp_virtual; ++ links[i].num_cpus = ARRAY_SIZE(sof_sp_virtual); ++ } + links[i].platforms = sof_component; + links[i].num_platforms = ARRAY_SIZE(sof_component); + links[i].dpcm_playback = 1; +diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c +index c01e31175015c..9c0accf5e1888 100644 +--- a/sound/soc/codecs/wm_adsp.c ++++ b/sound/soc/codecs/wm_adsp.c +@@ -739,19 +739,25 @@ static int wm_adsp_request_firmware_file(struct wm_adsp *dsp, + const char *filetype) + { + struct cs_dsp *cs_dsp = &dsp->cs_dsp; ++ const char *fwf; + char *s, c; + int ret = 0; + ++ if (dsp->fwf_name) ++ fwf = dsp->fwf_name; ++ else ++ fwf = dsp->cs_dsp.name; ++ + if (system_name && asoc_component_prefix) + *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s-%s.%s", dir, dsp->part, +- dsp->fwf_name, wm_adsp_fw[dsp->fw].file, system_name, ++ fwf, wm_adsp_fw[dsp->fw].file, system_name, + asoc_component_prefix, filetype); + else if (system_name) + *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s.%s", dir, dsp->part, +- dsp->fwf_name, wm_adsp_fw[dsp->fw].file, system_name, ++ fwf, wm_adsp_fw[dsp->fw].file, system_name, + filetype); + else +- *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s.%s", dir, dsp->part, dsp->fwf_name, ++ *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s.%s", dir, dsp->part, fwf, + wm_adsp_fw[dsp->fw].file, filetype); + + if (*filename == NULL) +@@ -863,29 +869,18 @@ static int wm_adsp_request_firmware_files(struct wm_adsp *dsp, + } + + adsp_err(dsp, "Failed to request firmware <%s>%s-%s-%s<-%s<%s>>.wmfw\n", +- cirrus_dir, dsp->part, dsp->fwf_name, wm_adsp_fw[dsp->fw].file, +- system_name, asoc_component_prefix); ++ 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); + + return -ENOENT; + } + + static int wm_adsp_common_init(struct wm_adsp *dsp) + { +- char *p; +- + INIT_LIST_HEAD(&dsp->compr_list); + INIT_LIST_HEAD(&dsp->buffer_list); + +- if (!dsp->fwf_name) { +- p = devm_kstrdup(dsp->cs_dsp.dev, dsp->cs_dsp.name, GFP_KERNEL); +- if (!p) +- return -ENOMEM; +- +- dsp->fwf_name = p; +- for (; *p != 0; ++p) +- *p = tolower(*p); +- } +- + return 0; + } + +diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c +index 702386823d172..f41c309558579 100644 +--- a/sound/soc/sunxi/sun4i-spdif.c ++++ b/sound/soc/sunxi/sun4i-spdif.c +@@ -577,6 +577,11 @@ static const struct of_device_id sun4i_spdif_of_match[] = { + .compatible = "allwinner,sun50i-h6-spdif", + .data = &sun50i_h6_spdif_quirks, + }, ++ { ++ .compatible = "allwinner,sun50i-h616-spdif", ++ /* Essentially the same as the H6, but without RX */ ++ .data = &sun50i_h6_spdif_quirks, ++ }, + { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(of, sun4i_spdif_of_match); +diff --git a/sound/usb/clock.c b/sound/usb/clock.c +index 33db334e65566..a676ad093d189 100644 +--- a/sound/usb/clock.c ++++ b/sound/usb/clock.c +@@ -328,8 +328,16 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, + if (chip->quirk_flags & QUIRK_FLAG_SKIP_CLOCK_SELECTOR) + return ret; + err = uac_clock_selector_set_val(chip, entity_id, cur); +- if (err < 0) ++ if (err < 0) { ++ if (pins == 1) { ++ usb_audio_dbg(chip, ++ "%s(): selector returned an error, " ++ "assuming a firmware bug, id %d, ret %d\n", ++ __func__, clock_id, err); ++ return ret; ++ } + return err; ++ } + } + + if (!validate || ret > 0 || !chip->autoclock) +diff --git a/sound/usb/format.c b/sound/usb/format.c +index ab5fed9f55b60..3b45d0ee76938 100644 +--- a/sound/usb/format.c ++++ b/sound/usb/format.c +@@ -470,9 +470,11 @@ static int validate_sample_rate_table_v2v3(struct snd_usb_audio *chip, + int clock) + { + struct usb_device *dev = chip->dev; ++ struct usb_host_interface *alts; + unsigned int *table; + unsigned int nr_rates; + int i, err; ++ u32 bmControls; + + /* performing the rate verification may lead to unexpected USB bus + * behavior afterwards by some unknown reason. Do this only for the +@@ -481,6 +483,24 @@ static int validate_sample_rate_table_v2v3(struct snd_usb_audio *chip, + if (!(chip->quirk_flags & QUIRK_FLAG_VALIDATE_RATES)) + return 0; /* don't perform the validation as default */ + ++ alts = snd_usb_get_host_interface(chip, fp->iface, fp->altsetting); ++ if (!alts) ++ return 0; ++ ++ if (fp->protocol == UAC_VERSION_3) { ++ struct uac3_as_header_descriptor *as = snd_usb_find_csint_desc( ++ alts->extra, alts->extralen, NULL, UAC_AS_GENERAL); ++ bmControls = le32_to_cpu(as->bmControls); ++ } else { ++ struct uac2_as_header_descriptor *as = snd_usb_find_csint_desc( ++ alts->extra, alts->extralen, NULL, UAC_AS_GENERAL); ++ bmControls = as->bmControls; ++ } ++ ++ if (!uac_v2v3_control_is_readable(bmControls, ++ UAC2_AS_VAL_ALT_SETTINGS)) ++ return 0; ++ + table = kcalloc(fp->nr_rates, sizeof(*table), GFP_KERNEL); + if (!table) + return -ENOMEM; +diff --git a/tools/net/ynl/lib/ynl.c b/tools/net/ynl/lib/ynl.c +index 830d25097009a..591f5f50ddaab 100644 +--- a/tools/net/ynl/lib/ynl.c ++++ b/tools/net/ynl/lib/ynl.c +@@ -462,6 +462,8 @@ ynl_gemsg_start_dump(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version) + + int ynl_recv_ack(struct ynl_sock *ys, int ret) + { ++ struct ynl_parse_arg yarg = { .ys = ys, }; ++ + if (!ret) { + yerr(ys, YNL_ERROR_EXPECT_ACK, + "Expecting an ACK but nothing received"); +@@ -474,7 +476,7 @@ int ynl_recv_ack(struct ynl_sock *ys, int ret) + return ret; + } + return mnl_cb_run(ys->rx_buf, ret, ys->seq, ys->portid, +- ynl_cb_null, ys); ++ ynl_cb_null, &yarg); + } + + int ynl_cb_null(const struct nlmsghdr *nlh, void *data) +@@ -582,7 +584,13 @@ static int ynl_sock_read_family(struct ynl_sock *ys, const char *family_name) + return err; + } + +- return ynl_recv_ack(ys, err); ++ err = ynl_recv_ack(ys, err); ++ if (err < 0) { ++ free(ys->mcast_groups); ++ return err; ++ } ++ ++ return 0; + } + + struct ynl_sock * +@@ -737,11 +745,14 @@ static int ynl_ntf_parse(struct ynl_sock *ys, const struct nlmsghdr *nlh) + + static int ynl_ntf_trampoline(const struct nlmsghdr *nlh, void *data) + { +- return ynl_ntf_parse((struct ynl_sock *)data, nlh); ++ struct ynl_parse_arg *yarg = data; ++ ++ return ynl_ntf_parse(yarg->ys, nlh); + } + + int ynl_ntf_check(struct ynl_sock *ys) + { ++ struct ynl_parse_arg yarg = { .ys = ys, }; + ssize_t len; + int err; + +@@ -763,7 +774,7 @@ int ynl_ntf_check(struct ynl_sock *ys) + return len; + + err = mnl_cb_run2(ys->rx_buf, len, ys->seq, ys->portid, +- ynl_ntf_trampoline, ys, ++ ynl_ntf_trampoline, &yarg, + ynl_cb_array, NLMSG_MIN_TYPE); + if (err < 0) + return err; +diff --git a/tools/testing/selftests/drivers/net/bonding/bond_options.sh b/tools/testing/selftests/drivers/net/bonding/bond_options.sh +index d508486cc0bdc..9a3d3c389dadd 100755 +--- a/tools/testing/selftests/drivers/net/bonding/bond_options.sh ++++ b/tools/testing/selftests/drivers/net/bonding/bond_options.sh +@@ -62,6 +62,8 @@ prio_test() + + # create bond + bond_reset "${param}" ++ # set active_slave to primary eth1 specifically ++ ip -n ${s_ns} link set bond0 type bond active_slave eth1 + + # check bonding member prio value + ip -n ${s_ns} link set eth0 type bond_slave prio 0 +diff --git a/tools/testing/selftests/iommu/config b/tools/testing/selftests/iommu/config +index 6c4f901d6fed3..110d73917615d 100644 +--- a/tools/testing/selftests/iommu/config ++++ b/tools/testing/selftests/iommu/config +@@ -1,2 +1,3 @@ +-CONFIG_IOMMUFD +-CONFIG_IOMMUFD_TEST ++CONFIG_IOMMUFD=y ++CONFIG_FAULT_INJECTION=y ++CONFIG_IOMMUFD_TEST=y +diff --git a/tools/testing/selftests/mm/uffd-unit-tests.c b/tools/testing/selftests/mm/uffd-unit-tests.c +index 2709a34a39c52..2c68709062da5 100644 +--- a/tools/testing/selftests/mm/uffd-unit-tests.c ++++ b/tools/testing/selftests/mm/uffd-unit-tests.c +@@ -1309,6 +1309,12 @@ int main(int argc, char *argv[]) + continue; + + uffd_test_start("%s on %s", test->name, mem_type->name); ++ if ((mem_type->mem_flag == MEM_HUGETLB || ++ mem_type->mem_flag == MEM_HUGETLB_PRIVATE) && ++ (default_huge_page_size() == 0)) { ++ uffd_test_skip("huge page size is 0, feature missing?"); ++ continue; ++ } + if (!uffd_feature_supported(test)) { + uffd_test_skip("feature missing"); + continue; +diff --git a/tools/testing/selftests/net/forwarding/tc_actions.sh b/tools/testing/selftests/net/forwarding/tc_actions.sh +index b0f5e55d2d0b2..5896296365022 100755 +--- a/tools/testing/selftests/net/forwarding/tc_actions.sh ++++ b/tools/testing/selftests/net/forwarding/tc_actions.sh +@@ -235,9 +235,6 @@ mirred_egress_to_ingress_tcp_test() + check_err $? "didn't mirred redirect ICMP" + tc_check_packets "dev $h1 ingress" 102 10 + check_err $? "didn't drop mirred ICMP" +- local overlimits=$(tc_rule_stats_get ${h1} 101 egress .overlimits) +- test ${overlimits} = 10 +- check_err $? "wrong overlimits, expected 10 got ${overlimits}" + + tc filter del dev $h1 egress protocol ip pref 100 handle 100 flower + tc filter del dev $h1 egress protocol ip pref 101 handle 101 flower +diff --git a/tools/testing/selftests/net/mptcp/diag.sh b/tools/testing/selftests/net/mptcp/diag.sh +index 85a8ee9395b39..4d8c59be1b30c 100755 +--- a/tools/testing/selftests/net/mptcp/diag.sh ++++ b/tools/testing/selftests/net/mptcp/diag.sh +@@ -56,14 +56,14 @@ __chk_nr() + local command="$1" + local expected=$2 + local msg="$3" +- local skip="${4:-SKIP}" ++ local skip="${4-SKIP}" + local nr + + nr=$(eval $command) + + printf "%-50s" "$msg" +- if [ $nr != $expected ]; then +- if [ $nr = "$skip" ] && ! mptcp_lib_expect_all_features; then ++ if [ "$nr" != "$expected" ]; then ++ if [ "$nr" = "$skip" ] && ! mptcp_lib_expect_all_features; then + echo "[ skip ] Feature probably not supported" + mptcp_lib_result_skip "${msg}" + else +@@ -166,9 +166,13 @@ chk_msk_listen() + chk_msk_inuse() + { + local expected=$1 +- local msg="$2" ++ local msg="....chk ${2:-${expected}} msk in use" + local listen_nr + ++ if [ "${expected}" -eq 0 ]; then ++ msg+=" after flush" ++ fi ++ + listen_nr=$(ss -N "${ns}" -Ml | grep -c LISTEN) + expected=$((expected + listen_nr)) + +@@ -179,7 +183,7 @@ chk_msk_inuse() + sleep 0.1 + done + +- __chk_nr get_msk_inuse $expected "$msg" 0 ++ __chk_nr get_msk_inuse $expected "${msg}" 0 + } + + # $1: ns, $2: port +@@ -199,6 +203,20 @@ wait_local_port_listen() + done + } + ++# $1: cestab nr ++chk_msk_cestab() ++{ ++ local expected=$1 ++ local msg="....chk ${2:-${expected}} cestab" ++ ++ if [ "${expected}" -eq 0 ]; then ++ msg+=" after flush" ++ fi ++ ++ __chk_nr "mptcp_lib_get_counter ${ns} MPTcpExtMPCurrEstab" \ ++ "${expected}" "${msg}" "" ++} ++ + wait_connected() + { + local listener_ns="${1}" +@@ -235,10 +253,12 @@ wait_connected $ns 10000 + chk_msk_nr 2 "after MPC handshake " + chk_msk_remote_key_nr 2 "....chk remote_key" + chk_msk_fallback_nr 0 "....chk no fallback" +-chk_msk_inuse 2 "....chk 2 msk in use" ++chk_msk_inuse 2 ++chk_msk_cestab 2 + flush_pids + +-chk_msk_inuse 0 "....chk 0 msk in use after flush" ++chk_msk_inuse 0 "2->0" ++chk_msk_cestab 0 "2->0" + + echo "a" | \ + timeout ${timeout_test} \ +@@ -253,10 +273,12 @@ echo "b" | \ + 127.0.0.1 >/dev/null & + wait_connected $ns 10001 + chk_msk_fallback_nr 1 "check fallback" +-chk_msk_inuse 1 "....chk 1 msk in use" ++chk_msk_inuse 1 ++chk_msk_cestab 1 + flush_pids + +-chk_msk_inuse 0 "....chk 0 msk in use after flush" ++chk_msk_inuse 0 "1->0" ++chk_msk_cestab 0 "1->0" + + NR_CLIENTS=100 + for I in `seq 1 $NR_CLIENTS`; do +@@ -277,10 +299,12 @@ for I in `seq 1 $NR_CLIENTS`; do + done + + wait_msk_nr $((NR_CLIENTS*2)) "many msk socket present" +-chk_msk_inuse $((NR_CLIENTS*2)) "....chk many msk in use" ++chk_msk_inuse $((NR_CLIENTS*2)) "many" ++chk_msk_cestab $((NR_CLIENTS*2)) "many" + flush_pids + +-chk_msk_inuse 0 "....chk 0 msk in use after flush" ++chk_msk_inuse 0 "many->0" ++chk_msk_cestab 0 "many->0" + + mptcp_lib_result_print_all_tap + exit $ret +diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.sh b/tools/testing/selftests/net/mptcp/mptcp_connect.sh +index b1fc8afd072dc..10cd322e05c42 100755 +--- a/tools/testing/selftests/net/mptcp/mptcp_connect.sh ++++ b/tools/testing/selftests/net/mptcp/mptcp_connect.sh +@@ -341,21 +341,6 @@ do_ping() + return 0 + } + +-# $1: ns, $2: MIB counter +-get_mib_counter() +-{ +- local listener_ns="${1}" +- local mib="${2}" +- +- # strip the header +- ip netns exec "${listener_ns}" \ +- nstat -z -a "${mib}" | \ +- tail -n+2 | \ +- while read a count c rest; do +- echo $count +- done +-} +- + # $1: ns, $2: port + wait_local_port_listen() + { +@@ -441,12 +426,12 @@ do_transfer() + nstat -n + fi + +- local stat_synrx_last_l=$(get_mib_counter "${listener_ns}" "MPTcpExtMPCapableSYNRX") +- local stat_ackrx_last_l=$(get_mib_counter "${listener_ns}" "MPTcpExtMPCapableACKRX") +- local stat_cookietx_last=$(get_mib_counter "${listener_ns}" "TcpExtSyncookiesSent") +- local stat_cookierx_last=$(get_mib_counter "${listener_ns}" "TcpExtSyncookiesRecv") +- local stat_csum_err_s=$(get_mib_counter "${listener_ns}" "MPTcpExtDataCsumErr") +- local stat_csum_err_c=$(get_mib_counter "${connector_ns}" "MPTcpExtDataCsumErr") ++ local stat_synrx_last_l=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtMPCapableSYNRX") ++ local stat_ackrx_last_l=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtMPCapableACKRX") ++ local stat_cookietx_last=$(mptcp_lib_get_counter "${listener_ns}" "TcpExtSyncookiesSent") ++ local stat_cookierx_last=$(mptcp_lib_get_counter "${listener_ns}" "TcpExtSyncookiesRecv") ++ local stat_csum_err_s=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtDataCsumErr") ++ local stat_csum_err_c=$(mptcp_lib_get_counter "${connector_ns}" "MPTcpExtDataCsumErr") + + timeout ${timeout_test} \ + ip netns exec ${listener_ns} \ +@@ -509,11 +494,11 @@ do_transfer() + check_transfer $cin $sout "file received by server" + rets=$? + +- local stat_synrx_now_l=$(get_mib_counter "${listener_ns}" "MPTcpExtMPCapableSYNRX") +- local stat_ackrx_now_l=$(get_mib_counter "${listener_ns}" "MPTcpExtMPCapableACKRX") +- local stat_cookietx_now=$(get_mib_counter "${listener_ns}" "TcpExtSyncookiesSent") +- local stat_cookierx_now=$(get_mib_counter "${listener_ns}" "TcpExtSyncookiesRecv") +- local stat_ooo_now=$(get_mib_counter "${listener_ns}" "TcpExtTCPOFOQueue") ++ local stat_synrx_now_l=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtMPCapableSYNRX") ++ local stat_ackrx_now_l=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtMPCapableACKRX") ++ local stat_cookietx_now=$(mptcp_lib_get_counter "${listener_ns}" "TcpExtSyncookiesSent") ++ local stat_cookierx_now=$(mptcp_lib_get_counter "${listener_ns}" "TcpExtSyncookiesRecv") ++ local stat_ooo_now=$(mptcp_lib_get_counter "${listener_ns}" "TcpExtTCPOFOQueue") + + expect_synrx=$((stat_synrx_last_l)) + expect_ackrx=$((stat_ackrx_last_l)) +@@ -542,8 +527,8 @@ do_transfer() + fi + + if $checksum; then +- local csum_err_s=$(get_mib_counter "${listener_ns}" "MPTcpExtDataCsumErr") +- local csum_err_c=$(get_mib_counter "${connector_ns}" "MPTcpExtDataCsumErr") ++ local csum_err_s=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtDataCsumErr") ++ local csum_err_c=$(mptcp_lib_get_counter "${connector_ns}" "MPTcpExtDataCsumErr") + + local csum_err_s_nr=$((csum_err_s - stat_csum_err_s)) + if [ $csum_err_s_nr -gt 0 ]; then +diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh +index ed665e0057d33..be10b971e912b 100755 +--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh ++++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh +@@ -611,25 +611,9 @@ wait_local_port_listen() + done + } + +-# $1: ns ; $2: counter +-get_counter() +-{ +- local ns="${1}" +- local counter="${2}" +- local count +- +- count=$(ip netns exec ${ns} nstat -asz "${counter}" | awk 'NR==1 {next} {print $2}') +- if [ -z "${count}" ]; then +- mptcp_lib_fail_if_expected_feature "${counter} counter" +- return 1 +- fi +- +- echo "${count}" +-} +- + rm_addr_count() + { +- get_counter "${1}" "MPTcpExtRmAddr" ++ mptcp_lib_get_counter "${1}" "MPTcpExtRmAddr" + } + + # $1: ns, $2: old rm_addr counter in $ns +@@ -649,7 +633,7 @@ wait_rm_addr() + + rm_sf_count() + { +- get_counter "${1}" "MPTcpExtRmSubflow" ++ mptcp_lib_get_counter "${1}" "MPTcpExtRmSubflow" + } + + # $1: ns, $2: old rm_sf counter in $ns +@@ -672,11 +656,11 @@ wait_mpj() + local ns="${1}" + local cnt old_cnt + +- old_cnt=$(get_counter ${ns} "MPTcpExtMPJoinAckRx") ++ old_cnt=$(mptcp_lib_get_counter ${ns} "MPTcpExtMPJoinAckRx") + + local i + for i in $(seq 10); do +- cnt=$(get_counter ${ns} "MPTcpExtMPJoinAckRx") ++ cnt=$(mptcp_lib_get_counter ${ns} "MPTcpExtMPJoinAckRx") + [ "$cnt" = "${old_cnt}" ] || break + sleep 0.1 + done +@@ -688,13 +672,6 @@ kill_events_pids() + mptcp_lib_kill_wait $evts_ns2_pid + } + +-kill_tests_wait() +-{ +- #shellcheck disable=SC2046 +- kill -SIGUSR1 $(ip netns pids $ns2) $(ip netns pids $ns1) +- wait +-} +- + pm_nl_set_limits() + { + local ns=$1 +@@ -1278,7 +1255,7 @@ chk_csum_nr() + fi + + print_check "sum" +- count=$(get_counter ${ns1} "MPTcpExtDataCsumErr") ++ count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtDataCsumErr") + if [ "$count" != "$csum_ns1" ]; then + extra_msg="$extra_msg ns1=$count" + fi +@@ -1291,7 +1268,7 @@ chk_csum_nr() + print_ok + fi + print_check "csum" +- count=$(get_counter ${ns2} "MPTcpExtDataCsumErr") ++ count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtDataCsumErr") + if [ "$count" != "$csum_ns2" ]; then + extra_msg="$extra_msg ns2=$count" + fi +@@ -1335,7 +1312,7 @@ chk_fail_nr() + fi + + print_check "ftx" +- count=$(get_counter ${ns_tx} "MPTcpExtMPFailTx") ++ count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMPFailTx") + if [ "$count" != "$fail_tx" ]; then + extra_msg="$extra_msg,tx=$count" + fi +@@ -1349,7 +1326,7 @@ chk_fail_nr() + fi + + print_check "failrx" +- count=$(get_counter ${ns_rx} "MPTcpExtMPFailRx") ++ count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtMPFailRx") + if [ "$count" != "$fail_rx" ]; then + extra_msg="$extra_msg,rx=$count" + fi +@@ -1382,7 +1359,7 @@ chk_fclose_nr() + fi + + print_check "ctx" +- count=$(get_counter ${ns_tx} "MPTcpExtMPFastcloseTx") ++ count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMPFastcloseTx") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$fclose_tx" ]; then +@@ -1393,7 +1370,7 @@ chk_fclose_nr() + fi + + print_check "fclzrx" +- count=$(get_counter ${ns_rx} "MPTcpExtMPFastcloseRx") ++ count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtMPFastcloseRx") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$fclose_rx" ]; then +@@ -1423,7 +1400,7 @@ chk_rst_nr() + fi + + print_check "rtx" +- count=$(get_counter ${ns_tx} "MPTcpExtMPRstTx") ++ count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMPRstTx") + if [ -z "$count" ]; then + print_skip + # accept more rst than expected except if we don't expect any +@@ -1435,7 +1412,7 @@ chk_rst_nr() + fi + + print_check "rstrx" +- count=$(get_counter ${ns_rx} "MPTcpExtMPRstRx") ++ count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtMPRstRx") + if [ -z "$count" ]; then + print_skip + # accept more rst than expected except if we don't expect any +@@ -1456,7 +1433,7 @@ chk_infi_nr() + local count + + print_check "itx" +- count=$(get_counter ${ns2} "MPTcpExtInfiniteMapTx") ++ count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtInfiniteMapTx") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$infi_tx" ]; then +@@ -1466,7 +1443,7 @@ chk_infi_nr() + fi + + print_check "infirx" +- count=$(get_counter ${ns1} "MPTcpExtInfiniteMapRx") ++ count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtInfiniteMapRx") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$infi_rx" ]; then +@@ -1495,7 +1472,7 @@ chk_join_nr() + fi + + print_check "syn" +- count=$(get_counter ${ns1} "MPTcpExtMPJoinSynRx") ++ count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinSynRx") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$syn_nr" ]; then +@@ -1506,7 +1483,7 @@ chk_join_nr() + + print_check "synack" + with_cookie=$(ip netns exec $ns2 sysctl -n net.ipv4.tcp_syncookies) +- count=$(get_counter ${ns2} "MPTcpExtMPJoinSynAckRx") ++ count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtMPJoinSynAckRx") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$syn_ack_nr" ]; then +@@ -1523,7 +1500,7 @@ chk_join_nr() + fi + + print_check "ack" +- count=$(get_counter ${ns1} "MPTcpExtMPJoinAckRx") ++ count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinAckRx") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$ack_nr" ]; then +@@ -1556,8 +1533,8 @@ chk_stale_nr() + + print_check "stale" + +- stale_nr=$(get_counter ${ns} "MPTcpExtSubflowStale") +- recover_nr=$(get_counter ${ns} "MPTcpExtSubflowRecover") ++ stale_nr=$(mptcp_lib_get_counter ${ns} "MPTcpExtSubflowStale") ++ recover_nr=$(mptcp_lib_get_counter ${ns} "MPTcpExtSubflowRecover") + if [ -z "$stale_nr" ] || [ -z "$recover_nr" ]; then + print_skip + elif [ $stale_nr -lt $stale_min ] || +@@ -1594,7 +1571,7 @@ chk_add_nr() + timeout=$(ip netns exec $ns1 sysctl -n net.mptcp.add_addr_timeout) + + print_check "add" +- count=$(get_counter ${ns2} "MPTcpExtAddAddr") ++ count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtAddAddr") + if [ -z "$count" ]; then + print_skip + # if the test configured a short timeout tolerate greater then expected +@@ -1606,7 +1583,7 @@ chk_add_nr() + fi + + print_check "echo" +- count=$(get_counter ${ns1} "MPTcpExtEchoAdd") ++ count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtEchoAdd") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$echo_nr" ]; then +@@ -1617,7 +1594,7 @@ chk_add_nr() + + if [ $port_nr -gt 0 ]; then + print_check "pt" +- count=$(get_counter ${ns2} "MPTcpExtPortAdd") ++ count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtPortAdd") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$port_nr" ]; then +@@ -1627,7 +1604,7 @@ chk_add_nr() + fi + + print_check "syn" +- count=$(get_counter ${ns1} "MPTcpExtMPJoinPortSynRx") ++ count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinPortSynRx") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$syn_nr" ]; then +@@ -1638,7 +1615,7 @@ chk_add_nr() + fi + + print_check "synack" +- count=$(get_counter ${ns2} "MPTcpExtMPJoinPortSynAckRx") ++ count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtMPJoinPortSynAckRx") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$syn_ack_nr" ]; then +@@ -1649,7 +1626,7 @@ chk_add_nr() + fi + + print_check "ack" +- count=$(get_counter ${ns1} "MPTcpExtMPJoinPortAckRx") ++ count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinPortAckRx") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$ack_nr" ]; then +@@ -1660,7 +1637,7 @@ chk_add_nr() + fi + + print_check "syn" +- count=$(get_counter ${ns1} "MPTcpExtMismatchPortSynRx") ++ count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMismatchPortSynRx") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$mis_syn_nr" ]; then +@@ -1671,7 +1648,7 @@ chk_add_nr() + fi + + print_check "ack" +- count=$(get_counter ${ns1} "MPTcpExtMismatchPortAckRx") ++ count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMismatchPortAckRx") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$mis_ack_nr" ]; then +@@ -1693,7 +1670,7 @@ chk_add_tx_nr() + timeout=$(ip netns exec $ns1 sysctl -n net.mptcp.add_addr_timeout) + + print_check "add TX" +- count=$(get_counter ${ns1} "MPTcpExtAddAddrTx") ++ count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtAddAddrTx") + if [ -z "$count" ]; then + print_skip + # if the test configured a short timeout tolerate greater then expected +@@ -1705,7 +1682,7 @@ chk_add_tx_nr() + fi + + print_check "echo TX" +- count=$(get_counter ${ns2} "MPTcpExtEchoAddTx") ++ count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtEchoAddTx") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$echo_tx_nr" ]; then +@@ -1743,7 +1720,7 @@ chk_rm_nr() + fi + + print_check "rm" +- count=$(get_counter ${addr_ns} "MPTcpExtRmAddr") ++ count=$(mptcp_lib_get_counter ${addr_ns} "MPTcpExtRmAddr") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$rm_addr_nr" ]; then +@@ -1753,13 +1730,13 @@ chk_rm_nr() + fi + + print_check "rmsf" +- count=$(get_counter ${subflow_ns} "MPTcpExtRmSubflow") ++ count=$(mptcp_lib_get_counter ${subflow_ns} "MPTcpExtRmSubflow") + if [ -z "$count" ]; then + print_skip + elif [ -n "$simult" ]; then + local cnt suffix + +- cnt=$(get_counter ${addr_ns} "MPTcpExtRmSubflow") ++ cnt=$(mptcp_lib_get_counter ${addr_ns} "MPTcpExtRmSubflow") + + # in case of simult flush, the subflow removal count on each side is + # unreliable +@@ -1788,7 +1765,7 @@ chk_rm_tx_nr() + local rm_addr_tx_nr=$1 + + print_check "rm TX" +- count=$(get_counter ${ns2} "MPTcpExtRmAddrTx") ++ count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtRmAddrTx") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$rm_addr_tx_nr" ]; then +@@ -1805,7 +1782,7 @@ chk_prio_nr() + local count + + print_check "ptx" +- count=$(get_counter ${ns1} "MPTcpExtMPPrioTx") ++ count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPPrioTx") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$mp_prio_nr_tx" ]; then +@@ -1815,7 +1792,7 @@ chk_prio_nr() + fi + + print_check "prx" +- count=$(get_counter ${ns1} "MPTcpExtMPPrioRx") ++ count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPPrioRx") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$mp_prio_nr_rx" ]; then +@@ -1915,7 +1892,7 @@ wait_attempt_fail() + while [ $time -lt $timeout_ms ]; do + local cnt + +- cnt=$(get_counter ${ns} "TcpAttemptFails") ++ cnt=$(mptcp_lib_get_counter ${ns} "TcpAttemptFails") + + [ "$cnt" = 1 ] && return 1 + time=$((time + 100)) +@@ -3433,7 +3410,7 @@ userspace_tests() + chk_rm_nr 1 1 invert + chk_mptcp_info subflows 0 subflows 0 + kill_events_pids +- wait $tests_pid ++ mptcp_lib_kill_wait $tests_pid + fi + + # userspace pm create destroy subflow +@@ -3452,7 +3429,7 @@ userspace_tests() + chk_rm_nr 1 1 + chk_mptcp_info subflows 0 subflows 0 + kill_events_pids +- wait $tests_pid ++ mptcp_lib_kill_wait $tests_pid + fi + } + +@@ -3466,7 +3443,8 @@ endpoint_tests() + pm_nl_set_limits $ns2 2 2 + pm_nl_add_endpoint $ns1 10.0.2.1 flags signal + speed=slow \ +- run_tests $ns1 $ns2 10.0.1.1 2>/dev/null & ++ run_tests $ns1 $ns2 10.0.1.1 & ++ local tests_pid=$! + + wait_mpj $ns1 + pm_nl_check_endpoint "creation" \ +@@ -3481,7 +3459,7 @@ endpoint_tests() + pm_nl_add_endpoint $ns2 10.0.2.2 flags signal + pm_nl_check_endpoint "modif is allowed" \ + $ns2 10.0.2.2 id 1 flags signal +- kill_tests_wait ++ mptcp_lib_kill_wait $tests_pid + fi + + if reset "delete and re-add" && +@@ -3490,7 +3468,8 @@ endpoint_tests() + pm_nl_set_limits $ns2 1 1 + pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow + test_linkfail=4 speed=20 \ +- run_tests $ns1 $ns2 10.0.1.1 2>/dev/null & ++ run_tests $ns1 $ns2 10.0.1.1 & ++ local tests_pid=$! + + wait_mpj $ns2 + chk_subflow_nr "before delete" 2 +@@ -3505,7 +3484,7 @@ endpoint_tests() + wait_mpj $ns2 + chk_subflow_nr "after re-add" 2 + chk_mptcp_info subflows 1 subflows 1 +- kill_tests_wait ++ mptcp_lib_kill_wait $tests_pid + fi + } + +diff --git a/tools/testing/selftests/net/mptcp/mptcp_lib.sh b/tools/testing/selftests/net/mptcp/mptcp_lib.sh +index 4cd4297ca86de..2b10f200de402 100644 +--- a/tools/testing/selftests/net/mptcp/mptcp_lib.sh ++++ b/tools/testing/selftests/net/mptcp/mptcp_lib.sh +@@ -216,3 +216,19 @@ mptcp_lib_kill_wait() { + kill "${1}" > /dev/null 2>&1 + wait "${1}" 2>/dev/null + } ++ ++# $1: ns, $2: MIB counter ++mptcp_lib_get_counter() { ++ local ns="${1}" ++ local counter="${2}" ++ local count ++ ++ count=$(ip netns exec "${ns}" nstat -asz "${counter}" | ++ awk 'NR==1 {next} {print $2}') ++ if [ -z "${count}" ]; then ++ mptcp_lib_fail_if_expected_feature "${counter} counter" ++ return 1 ++ fi ++ ++ echo "${count}" ++} +diff --git a/tools/testing/selftests/net/mptcp/pm_netlink.sh b/tools/testing/selftests/net/mptcp/pm_netlink.sh +index 8f4ff123a7eb9..71899a3ffa7a9 100755 +--- a/tools/testing/selftests/net/mptcp/pm_netlink.sh ++++ b/tools/testing/selftests/net/mptcp/pm_netlink.sh +@@ -183,7 +183,7 @@ check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags \ + subflow 10.0.1.1" " (nobackup)" + + # fullmesh support has been added later +-ip netns exec $ns1 ./pm_nl_ctl set id 1 flags fullmesh ++ip netns exec $ns1 ./pm_nl_ctl set id 1 flags fullmesh 2>/dev/null + if ip netns exec $ns1 ./pm_nl_ctl dump | grep -q "fullmesh" || + mptcp_lib_expect_all_features; then + check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags \ +@@ -194,6 +194,12 @@ subflow 10.0.1.1" " (nofullmesh)" + ip netns exec $ns1 ./pm_nl_ctl set id 1 flags backup,fullmesh + check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags \ + subflow,backup,fullmesh 10.0.1.1" " (backup,fullmesh)" ++else ++ for st in fullmesh nofullmesh backup,fullmesh; do ++ st=" (${st})" ++ printf "%-50s%s\n" "${st}" "[SKIP]" ++ mptcp_lib_result_skip "${st}" ++ done + fi + + mptcp_lib_result_print_all_tap +diff --git a/tools/testing/selftests/net/mptcp/simult_flows.sh b/tools/testing/selftests/net/mptcp/simult_flows.sh +index ce9203b817f88..9096bf5794888 100755 +--- a/tools/testing/selftests/net/mptcp/simult_flows.sh ++++ b/tools/testing/selftests/net/mptcp/simult_flows.sh +@@ -267,7 +267,8 @@ run_test() + [ $bail -eq 0 ] || exit $ret + fi + +- printf "%-60s" "$msg - reverse direction" ++ msg+=" - reverse direction" ++ printf "%-60s" "${msg}" + do_transfer $large $small $time + lret=$? + mptcp_lib_result_code "${lret}" "${msg}" +diff --git a/tools/testing/selftests/net/mptcp/userspace_pm.sh b/tools/testing/selftests/net/mptcp/userspace_pm.sh +index c44bf5c7c6e04..0e748068ee95e 100755 +--- a/tools/testing/selftests/net/mptcp/userspace_pm.sh ++++ b/tools/testing/selftests/net/mptcp/userspace_pm.sh +@@ -75,7 +75,7 @@ print_test() + { + test_name="${1}" + +- _printf "%-63s" "${test_name}" ++ _printf "%-68s" "${test_name}" + } + + print_results() +@@ -555,7 +555,7 @@ verify_subflow_events() + local remid + local info + +- info="${e_saddr} (${e_from}) => ${e_daddr} (${e_to})" ++ info="${e_saddr} (${e_from}) => ${e_daddr}:${e_dport} (${e_to})" + + if [ "$e_type" = "$SUB_ESTABLISHED" ] + then +@@ -887,9 +887,10 @@ test_prio() + + # Check TX + print_test "MP_PRIO TX" +- count=$(ip netns exec "$ns2" nstat -as | grep MPTcpExtMPPrioTx | awk '{print $2}') +- [ -z "$count" ] && count=0 +- if [ $count != 1 ]; then ++ count=$(mptcp_lib_get_counter "$ns2" "MPTcpExtMPPrioTx") ++ if [ -z "$count" ]; then ++ test_skip ++ elif [ $count != 1 ]; then + test_fail "Count != 1: ${count}" + else + test_pass +@@ -897,9 +898,10 @@ test_prio() + + # Check RX + print_test "MP_PRIO RX" +- count=$(ip netns exec "$ns1" nstat -as | grep MPTcpExtMPPrioRx | awk '{print $2}') +- [ -z "$count" ] && count=0 +- if [ $count != 1 ]; then ++ count=$(mptcp_lib_get_counter "$ns1" "MPTcpExtMPPrioRx") ++ if [ -z "$count" ]; then ++ test_skip ++ elif [ $count != 1 ]; then + test_fail "Count != 1: ${count}" + else + test_pass +diff --git a/tools/testing/selftests/riscv/hwprobe/cbo.c b/tools/testing/selftests/riscv/hwprobe/cbo.c +index c000942c80483..c537d52fafc58 100644 +--- a/tools/testing/selftests/riscv/hwprobe/cbo.c ++++ b/tools/testing/selftests/riscv/hwprobe/cbo.c +@@ -95,7 +95,7 @@ static void test_zicboz(void *arg) + block_size = pair.value; + ksft_test_result(rc == 0 && pair.key == RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE && + is_power_of_2(block_size), "Zicboz block size\n"); +- ksft_print_msg("Zicboz block size: %ld\n", block_size); ++ ksft_print_msg("Zicboz block size: %llu\n", block_size); + + illegal_insn = false; + cbo_zero(&mem[block_size]); +@@ -119,7 +119,7 @@ static void test_zicboz(void *arg) + for (j = 0; j < block_size; ++j) { + if (mem[i * block_size + j] != expected) { + ksft_test_result_fail("cbo.zero check\n"); +- ksft_print_msg("cbo.zero check: mem[%d] != 0x%x\n", ++ ksft_print_msg("cbo.zero check: mem[%llu] != 0x%x\n", + i * block_size + j, expected); + return; + } +@@ -199,7 +199,7 @@ int main(int argc, char **argv) + pair.key = RISCV_HWPROBE_KEY_IMA_EXT_0; + rc = riscv_hwprobe(&pair, 1, sizeof(cpu_set_t), (unsigned long *)&cpus, 0); + if (rc < 0) +- ksft_exit_fail_msg("hwprobe() failed with %d\n", rc); ++ ksft_exit_fail_msg("hwprobe() failed with %ld\n", rc); + assert(rc == 0 && pair.key == RISCV_HWPROBE_KEY_IMA_EXT_0); + + if (pair.value & RISCV_HWPROBE_EXT_ZICBOZ) { +diff --git a/tools/testing/selftests/riscv/hwprobe/hwprobe.c b/tools/testing/selftests/riscv/hwprobe/hwprobe.c +index c474891df3071..abb825811c70e 100644 +--- a/tools/testing/selftests/riscv/hwprobe/hwprobe.c ++++ b/tools/testing/selftests/riscv/hwprobe/hwprobe.c +@@ -29,7 +29,7 @@ int main(int argc, char **argv) + /* Fail if the kernel claims not to recognize a base key. */ + if ((i < 4) && (pairs[i].key != i)) + ksft_exit_fail_msg("Failed to recognize base key: key != i, " +- "key=%ld, i=%ld\n", pairs[i].key, i); ++ "key=%lld, i=%ld\n", pairs[i].key, i); + + if (pairs[i].key != RISCV_HWPROBE_KEY_BASE_BEHAVIOR) + continue; +@@ -37,7 +37,7 @@ int main(int argc, char **argv) + if (pairs[i].value & RISCV_HWPROBE_BASE_BEHAVIOR_IMA) + continue; + +- ksft_exit_fail_msg("Unexpected pair: (%ld, %ld)\n", pairs[i].key, pairs[i].value); ++ ksft_exit_fail_msg("Unexpected pair: (%lld, %llu)\n", pairs[i].key, pairs[i].value); + } + + out = riscv_hwprobe(pairs, 8, 0, 0, 0); +diff --git a/tools/testing/selftests/riscv/mm/mmap_test.h b/tools/testing/selftests/riscv/mm/mmap_test.h +index 9b8434f62f570..2e0db9c5be6c3 100644 +--- a/tools/testing/selftests/riscv/mm/mmap_test.h ++++ b/tools/testing/selftests/riscv/mm/mmap_test.h +@@ -18,6 +18,8 @@ struct addresses { + int *on_56_addr; + }; + ++// Only works on 64 bit ++#if __riscv_xlen == 64 + static inline void do_mmaps(struct addresses *mmap_addresses) + { + /* +@@ -50,6 +52,7 @@ static inline void do_mmaps(struct addresses *mmap_addresses) + mmap_addresses->on_56_addr = + mmap(on_56_bits, 5 * sizeof(int), prot, flags, 0, 0); + } ++#endif /* __riscv_xlen == 64 */ + + static inline int memory_layout(void) + { +diff --git a/tools/testing/selftests/riscv/vector/v_initval_nolibc.c b/tools/testing/selftests/riscv/vector/v_initval_nolibc.c +index 66764edb0d526..1dd94197da30c 100644 +--- a/tools/testing/selftests/riscv/vector/v_initval_nolibc.c ++++ b/tools/testing/selftests/riscv/vector/v_initval_nolibc.c +@@ -27,7 +27,7 @@ int main(void) + + datap = malloc(MAX_VSIZE); + if (!datap) { +- ksft_test_result_fail("fail to allocate memory for size = %lu\n", MAX_VSIZE); ++ ksft_test_result_fail("fail to allocate memory for size = %d\n", MAX_VSIZE); + exit(-1); + } + +diff --git a/tools/testing/selftests/riscv/vector/vstate_prctl.c b/tools/testing/selftests/riscv/vector/vstate_prctl.c +index b348b475be570..8ad94e08ff4d0 100644 +--- a/tools/testing/selftests/riscv/vector/vstate_prctl.c ++++ b/tools/testing/selftests/riscv/vector/vstate_prctl.c +@@ -68,7 +68,7 @@ int test_and_compare_child(long provided, long expected, int inherit) + } + rc = launch_test(inherit); + if (rc != expected) { +- ksft_test_result_fail("Test failed, check %d != %d\n", rc, ++ ksft_test_result_fail("Test failed, check %d != %ld\n", rc, + expected); + return -2; + } +@@ -87,7 +87,7 @@ int main(void) + pair.key = RISCV_HWPROBE_KEY_IMA_EXT_0; + rc = riscv_hwprobe(&pair, 1, 0, NULL, 0); + if (rc < 0) { +- ksft_test_result_fail("hwprobe() failed with %d\n", rc); ++ ksft_test_result_fail("hwprobe() failed with %ld\n", rc); + return -1; + } + |