diff options
-rw-r--r-- | 0000_README | 4 | ||||
-rw-r--r-- | 1012_linux-6.10.13.patch | 28977 |
2 files changed, 28981 insertions, 0 deletions
diff --git a/0000_README b/0000_README index f735905c..fdea4bd1 100644 --- a/0000_README +++ b/0000_README @@ -91,6 +91,10 @@ Patch: 1011_linux-6.10.12.patch From: https://www.kernel.org Desc: Linux 6.10.12 +Patch: 1012_linux-6.10.13.patch +From: https://www.kernel.org +Desc: Linux 6.10.13 + 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/1012_linux-6.10.13.patch b/1012_linux-6.10.13.patch new file mode 100644 index 00000000..0fe55b0f --- /dev/null +++ b/1012_linux-6.10.13.patch @@ -0,0 +1,28977 @@ +diff --git a/.gitignore b/.gitignore +index c59dc60ba62ef0..7acc74c54ded5b 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -136,7 +136,6 @@ GTAGS + # id-utils files + ID + +-*.orig + *~ + \#*# + +diff --git a/Documentation/ABI/testing/sysfs-bus-iio-filter-admv8818 b/Documentation/ABI/testing/sysfs-bus-iio-filter-admv8818 +index 31dbb390573ff2..c431f0a13cf502 100644 +--- a/Documentation/ABI/testing/sysfs-bus-iio-filter-admv8818 ++++ b/Documentation/ABI/testing/sysfs-bus-iio-filter-admv8818 +@@ -3,7 +3,7 @@ KernelVersion: + Contact: linux-iio@vger.kernel.org + Description: + Reading this returns the valid values that can be written to the +- on_altvoltage0_mode attribute: ++ filter_mode attribute: + + - auto -> Adjust bandpass filter to track changes in input clock rate. + - manual -> disable/unregister the clock rate notifier / input clock tracking. +diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst +index 50327c05be8d1b..39c52385f11fb3 100644 +--- a/Documentation/arch/arm64/silicon-errata.rst ++++ b/Documentation/arch/arm64/silicon-errata.rst +@@ -55,6 +55,8 @@ stable kernels. + +----------------+-----------------+-----------------+-----------------------------+ + | Ampere | AmpereOne | AC03_CPU_38 | AMPERE_ERRATUM_AC03_CPU_38 | + +----------------+-----------------+-----------------+-----------------------------+ ++| Ampere | AmpereOne AC04 | AC04_CPU_10 | AMPERE_ERRATUM_AC03_CPU_38 | +++----------------+-----------------+-----------------+-----------------------------+ + +----------------+-----------------+-----------------+-----------------------------+ + | ARM | Cortex-A510 | #2457168 | ARM64_ERRATUM_2457168 | + +----------------+-----------------+-----------------+-----------------------------+ +diff --git a/Documentation/devicetree/bindings/iio/magnetometer/asahi-kasei,ak8975.yaml b/Documentation/devicetree/bindings/iio/magnetometer/asahi-kasei,ak8975.yaml +index 9790f75fc669ef..fe5145d3b73cf2 100644 +--- a/Documentation/devicetree/bindings/iio/magnetometer/asahi-kasei,ak8975.yaml ++++ b/Documentation/devicetree/bindings/iio/magnetometer/asahi-kasei,ak8975.yaml +@@ -23,7 +23,6 @@ properties: + - ak8963 + - ak09911 + - ak09912 +- - ak09916 + deprecated: true + + reg: +diff --git a/Documentation/devicetree/bindings/pci/fsl,layerscape-pcie.yaml b/Documentation/devicetree/bindings/pci/fsl,layerscape-pcie.yaml +index 793986c5af7ff3..daeab5c0758d14 100644 +--- a/Documentation/devicetree/bindings/pci/fsl,layerscape-pcie.yaml ++++ b/Documentation/devicetree/bindings/pci/fsl,layerscape-pcie.yaml +@@ -22,18 +22,20 @@ description: + + properties: + compatible: +- enum: +- - fsl,ls1021a-pcie +- - fsl,ls2080a-pcie +- - fsl,ls2085a-pcie +- - fsl,ls2088a-pcie +- - fsl,ls1088a-pcie +- - fsl,ls1046a-pcie +- - fsl,ls1043a-pcie +- - fsl,ls1012a-pcie +- - fsl,ls1028a-pcie +- - fsl,lx2160a-pcie +- ++ oneOf: ++ - enum: ++ - fsl,ls1012a-pcie ++ - fsl,ls1021a-pcie ++ - fsl,ls1028a-pcie ++ - fsl,ls1043a-pcie ++ - fsl,ls1046a-pcie ++ - fsl,ls1088a-pcie ++ - fsl,ls2080a-pcie ++ - fsl,ls2085a-pcie ++ - fsl,ls2088a-pcie ++ - items: ++ - const: fsl,lx2160ar2-pcie ++ - const: fsl,ls2088a-pcie + reg: + maxItems: 2 + +diff --git a/Documentation/devicetree/bindings/spi/spi-nxp-fspi.yaml b/Documentation/devicetree/bindings/spi/spi-nxp-fspi.yaml +index 4a5f41bde00f3c..902db92da83207 100644 +--- a/Documentation/devicetree/bindings/spi/spi-nxp-fspi.yaml ++++ b/Documentation/devicetree/bindings/spi/spi-nxp-fspi.yaml +@@ -21,6 +21,7 @@ properties: + - nxp,imx8mm-fspi + - nxp,imx8mp-fspi + - nxp,imx8qxp-fspi ++ - nxp,imx8ulp-fspi + - nxp,lx2160a-fspi + - items: + - enum: +diff --git a/Documentation/driver-api/ipmi.rst b/Documentation/driver-api/ipmi.rst +index e224e47b6b0944..dfa021eacd63c4 100644 +--- a/Documentation/driver-api/ipmi.rst ++++ b/Documentation/driver-api/ipmi.rst +@@ -540,7 +540,7 @@ at module load time (for a module) with:: + alerts_broken + + The addresses are normal I2C addresses. The adapter is the string +-name of the adapter, as shown in /sys/class/i2c-adapter/i2c-<n>/name. ++name of the adapter, as shown in /sys/bus/i2c/devices/i2c-<n>/name. + It is *NOT* i2c-<n> itself. Also, the comparison is done ignoring + spaces, so if the name is "This is an I2C chip" you can say + adapter_name=ThisisanI2cchip. This is because it's hard to pass in +diff --git a/Documentation/filesystems/mount_api.rst b/Documentation/filesystems/mount_api.rst +index 9aaf6ef75eb53b..317934c9e8fcac 100644 +--- a/Documentation/filesystems/mount_api.rst ++++ b/Documentation/filesystems/mount_api.rst +@@ -645,6 +645,8 @@ The members are as follows: + fs_param_is_blockdev Blockdev path * Needs lookup + fs_param_is_path Path * Needs lookup + fs_param_is_fd File descriptor result->int_32 ++ fs_param_is_uid User ID (u32) result->uid ++ fs_param_is_gid Group ID (u32) result->gid + ======================= ======================= ===================== + + Note that if the value is of fs_param_is_bool type, fs_parse() will try +@@ -678,6 +680,8 @@ The members are as follows: + fsparam_bdev() fs_param_is_blockdev + fsparam_path() fs_param_is_path + fsparam_fd() fs_param_is_fd ++ fsparam_uid() fs_param_is_uid ++ fsparam_gid() fs_param_is_gid + ======================= =============================================== + + all of which take two arguments, name string and option number - for +@@ -784,8 +788,9 @@ process the parameters it is given. + option number (which it returns). + + If successful, and if the parameter type indicates the result is a +- boolean, integer or enum type, the value is converted by this function and +- the result stored in result->{boolean,int_32,uint_32,uint_64}. ++ boolean, integer, enum, uid, or gid type, the value is converted by this ++ function and the result stored in ++ result->{boolean,int_32,uint_32,uint_64,uid,gid}. + + If a match isn't initially made, the key is prefixed with "no" and no + value is present then an attempt will be made to look up the key with the +diff --git a/Documentation/virt/kvm/locking.rst b/Documentation/virt/kvm/locking.rst +index 02880d5552d5fa..198a5a8f26c2da 100644 +--- a/Documentation/virt/kvm/locking.rst ++++ b/Documentation/virt/kvm/locking.rst +@@ -9,7 +9,7 @@ KVM Lock Overview + + The acquisition orders for mutexes are as follows: + +-- cpus_read_lock() is taken outside kvm_lock ++- cpus_read_lock() is taken outside kvm_lock and kvm_usage_lock + + - kvm->lock is taken outside vcpu->mutex + +@@ -24,6 +24,13 @@ The acquisition orders for mutexes are as follows: + are taken on the waiting side when modifying memslots, so MMU notifiers + must not take either kvm->slots_lock or kvm->slots_arch_lock. + ++cpus_read_lock() vs kvm_lock: ++ ++- Taking cpus_read_lock() outside of kvm_lock is problematic, despite that ++ being the official ordering, as it is quite easy to unknowingly trigger ++ cpus_read_lock() while holding kvm_lock. Use caution when walking vm_list, ++ e.g. avoid complex operations when possible. ++ + For SRCU: + + - ``synchronize_srcu(&kvm->srcu)`` is called inside critical sections +@@ -227,10 +234,17 @@ time it will be set using the Dirty tracking mechanism described above. + :Type: mutex + :Arch: any + :Protects: - vm_list +- - kvm_usage_count ++ ++``kvm_usage_lock`` ++^^^^^^^^^^^^^^^^^^ ++ ++:Type: mutex ++:Arch: any ++:Protects: - kvm_usage_count + - hardware virtualization enable/disable +-:Comment: KVM also disables CPU hotplug via cpus_read_lock() during +- enable/disable. ++:Comment: Exists because using kvm_lock leads to deadlock (see earlier comment ++ on cpus_read_lock() vs kvm_lock). Note, KVM also disables CPU hotplug via ++ cpus_read_lock() when enabling/disabling virtualization. + + ``kvm->mn_invalidate_lock`` + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +@@ -290,11 +304,12 @@ time it will be set using the Dirty tracking mechanism described above. + wakeup. + + ``vendor_module_lock`` +-^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++^^^^^^^^^^^^^^^^^^^^^^ + :Type: mutex + :Arch: x86 + :Protects: loading a vendor module (kvm_amd or kvm_intel) +-:Comment: Exists because using kvm_lock leads to deadlock. cpu_hotplug_lock is +- taken outside of kvm_lock, e.g. in KVM's CPU online/offline callbacks, and +- many operations need to take cpu_hotplug_lock when loading a vendor module, +- e.g. updating static calls. ++:Comment: Exists because using kvm_lock leads to deadlock. kvm_lock is taken ++ in notifiers, e.g. __kvmclock_cpufreq_notifier(), that may be invoked while ++ cpu_hotplug_lock is held, e.g. from cpufreq_boost_trigger_state(), and many ++ operations need to take cpu_hotplug_lock when loading a vendor module, e.g. ++ updating static calls. +diff --git a/Makefile b/Makefile +index 175d7f27ea32a4..93731d0b1a04ac 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 10 +-SUBLEVEL = 12 ++SUBLEVEL = 13 + EXTRAVERSION = + NAME = Baby Opossum Posse + +diff --git a/arch/arm/boot/dts/microchip/sam9x60.dtsi b/arch/arm/boot/dts/microchip/sam9x60.dtsi +index 291540e5d81e76..d077afd5024db1 100644 +--- a/arch/arm/boot/dts/microchip/sam9x60.dtsi ++++ b/arch/arm/boot/dts/microchip/sam9x60.dtsi +@@ -1312,7 +1312,7 @@ rtt: rtc@fffffe20 { + compatible = "microchip,sam9x60-rtt", "atmel,at91sam9260-rtt"; + reg = <0xfffffe20 0x20>; + interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; +- clocks = <&clk32k 0>; ++ clocks = <&clk32k 1>; + }; + + pit: timer@fffffe40 { +@@ -1338,7 +1338,7 @@ rtc: rtc@fffffea8 { + compatible = "microchip,sam9x60-rtc", "atmel,at91sam9x5-rtc"; + reg = <0xfffffea8 0x100>; + interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; +- clocks = <&clk32k 0>; ++ clocks = <&clk32k 1>; + }; + + watchdog: watchdog@ffffff80 { +diff --git a/arch/arm/boot/dts/microchip/sama7g5.dtsi b/arch/arm/boot/dts/microchip/sama7g5.dtsi +index 75778be126a3d9..17bcdcf0cf4a05 100644 +--- a/arch/arm/boot/dts/microchip/sama7g5.dtsi ++++ b/arch/arm/boot/dts/microchip/sama7g5.dtsi +@@ -272,7 +272,7 @@ rtt: rtc@e001d020 { + compatible = "microchip,sama7g5-rtt", "microchip,sam9x60-rtt", "atmel,at91sam9260-rtt"; + reg = <0xe001d020 0x30>; + interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; +- clocks = <&clk32k 0>; ++ clocks = <&clk32k 1>; + }; + + clk32k: clock-controller@e001d050 { +diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-geam.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-geam.dts +index cdbb8c435cd6aa..601d89b904cdfb 100644 +--- a/arch/arm/boot/dts/nxp/imx/imx6ul-geam.dts ++++ b/arch/arm/boot/dts/nxp/imx/imx6ul-geam.dts +@@ -365,7 +365,7 @@ MX6UL_PAD_ENET1_RX_ER__PWM8_OUT 0x110b0 + }; + + pinctrl_tsc: tscgrp { +- fsl,pin = < ++ fsl,pins = < + MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0xb0 + MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0xb0 + MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0xb0 +diff --git a/arch/arm/boot/dts/nxp/imx/imx6ull-seeed-npi-dev-board.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-seeed-npi-dev-board.dtsi +index 6bb12e0bbc7ec6..50654dbf62e02c 100644 +--- a/arch/arm/boot/dts/nxp/imx/imx6ull-seeed-npi-dev-board.dtsi ++++ b/arch/arm/boot/dts/nxp/imx/imx6ull-seeed-npi-dev-board.dtsi +@@ -339,14 +339,14 @@ MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA 0x120b0 + }; + + pinctrl_uart1: uart1grp { +- fsl,pin = < ++ fsl,pins = < + MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1 + MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1 + >; + }; + + pinctrl_uart2: uart2grp { +- fsl,pin = < ++ fsl,pins = < + MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX 0x1b0b1 + MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX 0x1b0b1 + MX6UL_PAD_UART2_CTS_B__UART2_DCE_CTS 0x1b0b1 +@@ -355,7 +355,7 @@ MX6UL_PAD_UART2_RTS_B__UART2_DCE_RTS 0x1b0b1 + }; + + pinctrl_uart3: uart3grp { +- fsl,pin = < ++ fsl,pins = < + MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 0x1b0b1 + MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0x1b0b1 + MX6UL_PAD_UART3_CTS_B__UART3_DCE_CTS 0x1b0b1 +@@ -364,21 +364,21 @@ MX6UL_PAD_UART3_RTS_B__UART3_DCE_RTS 0x1b0b1 + }; + + pinctrl_uart4: uart4grp { +- fsl,pin = < ++ fsl,pins = < + MX6UL_PAD_UART4_TX_DATA__UART4_DCE_TX 0x1b0b1 + MX6UL_PAD_UART4_RX_DATA__UART4_DCE_RX 0x1b0b1 + >; + }; + + pinctrl_uart5: uart5grp { +- fsl,pin = < ++ fsl,pins = < + MX6UL_PAD_UART5_TX_DATA__UART5_DCE_TX 0x1b0b1 + MX6UL_PAD_UART5_RX_DATA__UART5_DCE_RX 0x1b0b1 + >; + }; + + pinctrl_usb_otg1_id: usbotg1idgrp { +- fsl,pin = < ++ fsl,pins = < + MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID 0x17059 + >; + }; +diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-zii-rmu2.dts b/arch/arm/boot/dts/nxp/imx/imx7d-zii-rmu2.dts +index 521493342fe972..8f5566027c25a2 100644 +--- a/arch/arm/boot/dts/nxp/imx/imx7d-zii-rmu2.dts ++++ b/arch/arm/boot/dts/nxp/imx/imx7d-zii-rmu2.dts +@@ -350,7 +350,7 @@ MX7D_PAD_SD3_RESET_B__SD3_RESET_B 0x59 + + &iomuxc_lpsr { + pinctrl_enet1_phy_interrupt: enet1phyinterruptgrp { +- fsl,phy = < ++ fsl,pins = < + MX7D_PAD_LPSR_GPIO1_IO02__GPIO1_IO2 0x08 + >; + }; +diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c +index 85a496ddc6197e..e9f72a529b5089 100644 +--- a/arch/arm/mach-ep93xx/clock.c ++++ b/arch/arm/mach-ep93xx/clock.c +@@ -359,7 +359,7 @@ static unsigned long ep93xx_div_recalc_rate(struct clk_hw *hw, + u32 val = __raw_readl(psc->reg); + u8 index = (val & psc->mask) >> psc->shift; + +- if (index > psc->num_div) ++ if (index >= psc->num_div) + return 0; + + return DIV_ROUND_UP_ULL(parent_rate, psc->div[index]); +diff --git a/arch/arm/mach-versatile/platsmp-realview.c b/arch/arm/mach-versatile/platsmp-realview.c +index 6965a1de727b07..d38b2e174257e8 100644 +--- a/arch/arm/mach-versatile/platsmp-realview.c ++++ b/arch/arm/mach-versatile/platsmp-realview.c +@@ -70,6 +70,7 @@ static void __init realview_smp_prepare_cpus(unsigned int max_cpus) + return; + } + map = syscon_node_to_regmap(np); ++ of_node_put(np); + if (IS_ERR(map)) { + pr_err("PLATSMP: No syscon regmap\n"); + return; +diff --git a/arch/arm/vfp/vfpinstr.h b/arch/arm/vfp/vfpinstr.h +index 3c7938fd40aad6..32090b0fb250b8 100644 +--- a/arch/arm/vfp/vfpinstr.h ++++ b/arch/arm/vfp/vfpinstr.h +@@ -64,33 +64,37 @@ + + #ifdef CONFIG_AS_VFP_VMRS_FPINST + +-#define fmrx(_vfp_) ({ \ +- u32 __v; \ +- asm(".fpu vfpv2\n" \ +- "vmrs %0, " #_vfp_ \ +- : "=r" (__v) : : "cc"); \ +- __v; \ +- }) +- +-#define fmxr(_vfp_,_var_) \ +- asm(".fpu vfpv2\n" \ +- "vmsr " #_vfp_ ", %0" \ +- : : "r" (_var_) : "cc") ++#define fmrx(_vfp_) ({ \ ++ u32 __v; \ ++ asm volatile (".fpu vfpv2\n" \ ++ "vmrs %0, " #_vfp_ \ ++ : "=r" (__v) : : "cc"); \ ++ __v; \ ++}) ++ ++#define fmxr(_vfp_, _var_) ({ \ ++ asm volatile (".fpu vfpv2\n" \ ++ "vmsr " #_vfp_ ", %0" \ ++ : : "r" (_var_) : "cc"); \ ++}) + + #else + + #define vfpreg(_vfp_) #_vfp_ + +-#define fmrx(_vfp_) ({ \ +- u32 __v; \ +- asm("mrc p10, 7, %0, " vfpreg(_vfp_) ", cr0, 0 @ fmrx %0, " #_vfp_ \ +- : "=r" (__v) : : "cc"); \ +- __v; \ +- }) +- +-#define fmxr(_vfp_,_var_) \ +- asm("mcr p10, 7, %0, " vfpreg(_vfp_) ", cr0, 0 @ fmxr " #_vfp_ ", %0" \ +- : : "r" (_var_) : "cc") ++#define fmrx(_vfp_) ({ \ ++ u32 __v; \ ++ asm volatile ("mrc p10, 7, %0, " vfpreg(_vfp_) "," \ ++ "cr0, 0 @ fmrx %0, " #_vfp_ \ ++ : "=r" (__v) : : "cc"); \ ++ __v; \ ++}) ++ ++#define fmxr(_vfp_, _var_) ({ \ ++ asm volatile ("mcr p10, 7, %0, " vfpreg(_vfp_) "," \ ++ "cr0, 0 @ fmxr " #_vfp_ ", %0" \ ++ : : "r" (_var_) : "cc"); \ ++}) + + #endif + +diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig +index 11bbdc15c6e5e2..cd9772b1fd95ee 100644 +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -422,7 +422,7 @@ config AMPERE_ERRATUM_AC03_CPU_38 + default y + help + This option adds an alternative code sequence to work around Ampere +- erratum AC03_CPU_38 on AmpereOne. ++ errata AC03_CPU_38 and AC04_CPU_10 on AmpereOne. + + The affected design reports FEAT_HAFDBS as not implemented in + ID_AA64MMFR1_EL1.HAFDBS, but (V)TCR_ELx.{HA,HD} are not RES0 +diff --git a/arch/arm64/boot/dts/exynos/exynos7885-jackpotlte.dts b/arch/arm64/boot/dts/exynos/exynos7885-jackpotlte.dts +index 47a389d9ff7d71..9d74fa6bfed9fb 100644 +--- a/arch/arm64/boot/dts/exynos/exynos7885-jackpotlte.dts ++++ b/arch/arm64/boot/dts/exynos/exynos7885-jackpotlte.dts +@@ -32,7 +32,7 @@ memory@80000000 { + device_type = "memory"; + reg = <0x0 0x80000000 0x3da00000>, + <0x0 0xc0000000 0x40000000>, +- <0x8 0x80000000 0x40000000>; ++ <0x8 0x80000000 0x80000000>; + }; + + gpio-keys { +diff --git a/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi b/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi +index 1807e9d6cb0e41..0a4838b35eab6e 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi +@@ -321,7 +321,8 @@ &dpi { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&dpi_pins_default>; + pinctrl-1 = <&dpi_pins_sleep>; +- status = "okay"; ++ /* TODO Re-enable after DP to Type-C port muxing can be described */ ++ status = "disabled"; + }; + + &dpi_out { +diff --git a/arch/arm64/boot/dts/mediatek/mt8186.dtsi b/arch/arm64/boot/dts/mediatek/mt8186.dtsi +index 4763ed5dc86cfb..d63a9defe73e17 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8186.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8186.dtsi +@@ -731,7 +731,7 @@ opp-850000000 { + opp-900000000-3 { + opp-hz = /bits/ 64 <900000000>; + opp-microvolt = <850000>; +- opp-supported-hw = <0x8>; ++ opp-supported-hw = <0xcf>; + }; + + opp-900000000-4 { +@@ -743,13 +743,13 @@ opp-900000000-4 { + opp-900000000-5 { + opp-hz = /bits/ 64 <900000000>; + opp-microvolt = <825000>; +- opp-supported-hw = <0x30>; ++ opp-supported-hw = <0x20>; + }; + + opp-950000000-3 { + opp-hz = /bits/ 64 <950000000>; + opp-microvolt = <900000>; +- opp-supported-hw = <0x8>; ++ opp-supported-hw = <0xcf>; + }; + + opp-950000000-4 { +@@ -761,13 +761,13 @@ opp-950000000-4 { + opp-950000000-5 { + opp-hz = /bits/ 64 <950000000>; + opp-microvolt = <850000>; +- opp-supported-hw = <0x30>; ++ opp-supported-hw = <0x20>; + }; + + opp-1000000000-3 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <950000>; +- opp-supported-hw = <0x8>; ++ opp-supported-hw = <0xcf>; + }; + + opp-1000000000-4 { +@@ -779,7 +779,7 @@ opp-1000000000-4 { + opp-1000000000-5 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <875000>; +- opp-supported-hw = <0x30>; ++ opp-supported-hw = <0x20>; + }; + }; + +diff --git a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi +index 4a11918da37048..5a2d65edf4740f 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi +@@ -1359,6 +1359,7 @@ &xhci1 { + rx-fifo-depth = <3072>; + vusb33-supply = <&mt6359_vusb_ldo_reg>; + vbus-supply = <&usb_vbus>; ++ mediatek,u3p-dis-msk = <1>; + }; + + &xhci2 { +diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi +index 2ee45752583c00..98c15eb68589a5 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi +@@ -3251,10 +3251,10 @@ dp_intf0: dp-intf@1c015000 { + compatible = "mediatek,mt8195-dp-intf"; + reg = <0 0x1c015000 0 0x1000>; + interrupts = <GIC_SPI 657 IRQ_TYPE_LEVEL_HIGH 0>; +- clocks = <&vdosys0 CLK_VDO0_DP_INTF0>, +- <&vdosys0 CLK_VDO0_DP_INTF0_DP_INTF>, ++ clocks = <&vdosys0 CLK_VDO0_DP_INTF0_DP_INTF>, ++ <&vdosys0 CLK_VDO0_DP_INTF0>, + <&apmixedsys CLK_APMIXED_TVDPLL1>; +- clock-names = "engine", "pixel", "pll"; ++ clock-names = "pixel", "engine", "pll"; + status = "disabled"; + }; + +@@ -3521,10 +3521,10 @@ dp_intf1: dp-intf@1c113000 { + reg = <0 0x1c113000 0 0x1000>; + interrupts = <GIC_SPI 513 IRQ_TYPE_LEVEL_HIGH 0>; + power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>; +- clocks = <&vdosys1 CLK_VDO1_DP_INTF0_MM>, +- <&vdosys1 CLK_VDO1_DPINTF>, ++ clocks = <&vdosys1 CLK_VDO1_DPINTF>, ++ <&vdosys1 CLK_VDO1_DP_INTF0_MM>, + <&apmixedsys CLK_APMIXED_TVDPLL2>; +- clock-names = "engine", "pixel", "pll"; ++ clock-names = "pixel", "engine", "pll"; + status = "disabled"; + }; + +diff --git a/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts b/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts +index 97634cc04e659f..e2634590ca81f7 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts ++++ b/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts +@@ -816,6 +816,7 @@ &xhci1 { + usb2-lpm-disable; + vusb33-supply = <&mt6359_vusb_ldo_reg>; + vbus-supply = <&vsys>; ++ mediatek,u3p-dis-msk = <1>; + status = "okay"; + }; + +diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3701-0008.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3701-0008.dtsi +index 553fa4ba1cd48a..62c4fdad0b600b 100644 +--- a/arch/arm64/boot/dts/nvidia/tegra234-p3701-0008.dtsi ++++ b/arch/arm64/boot/dts/nvidia/tegra234-p3701-0008.dtsi +@@ -44,39 +44,6 @@ i2c@c240000 { + status = "okay"; + }; + +- i2c@c250000 { +- power-sensor@41 { +- compatible = "ti,ina3221"; +- reg = <0x41>; +- #address-cells = <1>; +- #size-cells = <0>; +- +- input@0 { +- reg = <0x0>; +- label = "CVB_ATX_12V"; +- shunt-resistor-micro-ohms = <2000>; +- }; +- +- input@1 { +- reg = <0x1>; +- label = "CVB_ATX_3V3"; +- shunt-resistor-micro-ohms = <2000>; +- }; +- +- input@2 { +- reg = <0x2>; +- label = "CVB_ATX_5V"; +- shunt-resistor-micro-ohms = <2000>; +- }; +- }; +- +- power-sensor@44 { +- compatible = "ti,ina219"; +- reg = <0x44>; +- shunt-resistor = <2000>; +- }; +- }; +- + rtc@c2a0000 { + status = "okay"; + }; +diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002.dtsi +index 527f2f3aee3ad4..377f518bd3e57b 100644 +--- a/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002.dtsi ++++ b/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002.dtsi +@@ -183,6 +183,39 @@ usb@3610000 { + phy-names = "usb2-0", "usb2-1", "usb2-2", "usb2-3", + "usb3-0", "usb3-1", "usb3-2"; + }; ++ ++ i2c@c250000 { ++ power-sensor@41 { ++ compatible = "ti,ina3221"; ++ reg = <0x41>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ input@0 { ++ reg = <0x0>; ++ label = "CVB_ATX_12V"; ++ shunt-resistor-micro-ohms = <2000>; ++ }; ++ ++ input@1 { ++ reg = <0x1>; ++ label = "CVB_ATX_3V3"; ++ shunt-resistor-micro-ohms = <2000>; ++ }; ++ ++ input@2 { ++ reg = <0x2>; ++ label = "CVB_ATX_5V"; ++ shunt-resistor-micro-ohms = <2000>; ++ }; ++ }; ++ ++ power-sensor@44 { ++ compatible = "ti,ina219"; ++ reg = <0x44>; ++ shunt-resistor = <2000>; ++ }; ++ }; + }; + + vdd_3v3_dp: regulator-vdd-3v3-dp { +diff --git a/arch/arm64/boot/dts/qcom/sa8775p.dtsi b/arch/arm64/boot/dts/qcom/sa8775p.dtsi +index 490e0369f52993..3a51e79af1bb6c 100644 +--- a/arch/arm64/boot/dts/qcom/sa8775p.dtsi ++++ b/arch/arm64/boot/dts/qcom/sa8775p.dtsi +@@ -2104,6 +2104,7 @@ apps_smmu: iommu@15000000 { + reg = <0x0 0x15000000 0x0 0x100000>; + #iommu-cells = <2>; + #global-interrupts = <2>; ++ dma-coherent; + + interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>, +@@ -2242,6 +2243,7 @@ pcie_smmu: iommu@15200000 { + reg = <0x0 0x15200000 0x0 0x80000>; + #iommu-cells = <2>; + #global-interrupts = <2>; ++ dma-coherent; + + interrupts = <GIC_SPI 920 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 921 IRQ_TYPE_LEVEL_HIGH>, +diff --git a/arch/arm64/boot/dts/qcom/x1e80100.dtsi b/arch/arm64/boot/dts/qcom/x1e80100.dtsi +index 36c398e5fe5016..64d5f6e4c0b018 100644 +--- a/arch/arm64/boot/dts/qcom/x1e80100.dtsi ++++ b/arch/arm64/boot/dts/qcom/x1e80100.dtsi +@@ -3998,14 +3998,14 @@ mdss_dp2: displayport-controller@ae9a000 { + + assigned-clocks = <&dispcc DISP_CC_MDSS_DPTX2_LINK_CLK_SRC>, + <&dispcc DISP_CC_MDSS_DPTX2_PIXEL0_CLK_SRC>; +- assigned-clock-parents = <&mdss_dp2_phy 0>, +- <&mdss_dp2_phy 1>; ++ assigned-clock-parents = <&usb_1_ss2_qmpphy QMP_USB43DP_DP_LINK_CLK>, ++ <&usb_1_ss2_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>; + + operating-points-v2 = <&mdss_dp2_opp_table>; + + power-domains = <&rpmhpd RPMHPD_MMCX>; + +- phys = <&mdss_dp2_phy>; ++ phys = <&usb_1_ss2_qmpphy QMP_USB43DP_DP_PHY>; + phy-names = "dp"; + + #sound-dai-cells = <0>; +@@ -4189,8 +4189,8 @@ dispcc: clock-controller@af00000 { + <&usb_1_ss0_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>, + <&usb_1_ss1_qmpphy QMP_USB43DP_DP_LINK_CLK>, /* dp1 */ + <&usb_1_ss1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>, +- <&mdss_dp2_phy 0>, /* dp2 */ +- <&mdss_dp2_phy 1>, ++ <&usb_1_ss2_qmpphy QMP_USB43DP_DP_LINK_CLK>, /* dp2 */ ++ <&usb_1_ss2_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>, + <&mdss_dp3_phy 0>, /* dp3 */ + <&mdss_dp3_phy 1>; + power-domains = <&rpmhpd RPMHPD_MMCX>; +diff --git a/arch/arm64/boot/dts/renesas/r9a07g043u.dtsi b/arch/arm64/boot/dts/renesas/r9a07g043u.dtsi +index 18ef297db93363..20fb5e41c5988c 100644 +--- a/arch/arm64/boot/dts/renesas/r9a07g043u.dtsi ++++ b/arch/arm64/boot/dts/renesas/r9a07g043u.dtsi +@@ -210,8 +210,8 @@ gic: interrupt-controller@11900000 { + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; +- reg = <0x0 0x11900000 0 0x40000>, +- <0x0 0x11940000 0 0x60000>; ++ reg = <0x0 0x11900000 0 0x20000>, ++ <0x0 0x11940000 0 0x40000>; + interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW>; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/r9a07g044.dtsi b/arch/arm64/boot/dts/renesas/r9a07g044.dtsi +index 1a9891ba6c02c4..960537e401f4cf 100644 +--- a/arch/arm64/boot/dts/renesas/r9a07g044.dtsi ++++ b/arch/arm64/boot/dts/renesas/r9a07g044.dtsi +@@ -1043,8 +1043,8 @@ gic: interrupt-controller@11900000 { + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; +- reg = <0x0 0x11900000 0 0x40000>, +- <0x0 0x11940000 0 0x60000>; ++ reg = <0x0 0x11900000 0 0x20000>, ++ <0x0 0x11940000 0 0x40000>; + interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW>; + }; + +diff --git a/arch/arm64/boot/dts/renesas/r9a07g054.dtsi b/arch/arm64/boot/dts/renesas/r9a07g054.dtsi +index a2318478a66ba7..66894b676c01ec 100644 +--- a/arch/arm64/boot/dts/renesas/r9a07g054.dtsi ++++ b/arch/arm64/boot/dts/renesas/r9a07g054.dtsi +@@ -1051,8 +1051,8 @@ gic: interrupt-controller@11900000 { + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; +- reg = <0x0 0x11900000 0 0x40000>, +- <0x0 0x11940000 0 0x60000>; ++ reg = <0x0 0x11900000 0 0x20000>, ++ <0x0 0x11940000 0 0x40000>; + interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW>; + }; + +diff --git a/arch/arm64/boot/dts/renesas/r9a08g045.dtsi b/arch/arm64/boot/dts/renesas/r9a08g045.dtsi +index a2adc4e27ce979..17609d81af294f 100644 +--- a/arch/arm64/boot/dts/renesas/r9a08g045.dtsi ++++ b/arch/arm64/boot/dts/renesas/r9a08g045.dtsi +@@ -269,8 +269,8 @@ gic: interrupt-controller@12400000 { + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; +- reg = <0x0 0x12400000 0 0x40000>, +- <0x0 0x12440000 0 0x60000>; ++ reg = <0x0 0x12400000 0 0x20000>, ++ <0x0 0x12440000 0 0x40000>; + interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW>; + }; + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts +index 294eb2de263deb..f5e124b235c83c 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts +@@ -32,12 +32,12 @@ chosen { + backlight: edp-backlight { + compatible = "pwm-backlight"; + power-supply = <&vcc_12v>; +- pwms = <&pwm0 0 740740 0>; ++ pwms = <&pwm0 0 125000 0>; + }; + + bat: battery { + compatible = "simple-battery"; +- charge-full-design-microamp-hours = <9800000>; ++ charge-full-design-microamp-hours = <10000000>; + voltage-max-design-microvolt = <4350000>; + voltage-min-design-microvolt = <3000000>; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts +index a337f547caf538..6a02db4f073f29 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts +@@ -13,7 +13,7 @@ + + / { + model = "Hardkernel ODROID-M1"; +- compatible = "rockchip,rk3568-odroid-m1", "rockchip,rk3568"; ++ compatible = "hardkernel,odroid-m1", "rockchip,rk3568"; + + aliases { + ethernet0 = &gmac0; +diff --git a/arch/arm64/boot/dts/ti/k3-am654-idk.dtso b/arch/arm64/boot/dts/ti/k3-am654-idk.dtso +index 8bdb87fcbde007..1674ad564be1fd 100644 +--- a/arch/arm64/boot/dts/ti/k3-am654-idk.dtso ++++ b/arch/arm64/boot/dts/ti/k3-am654-idk.dtso +@@ -58,9 +58,7 @@ icssg0_eth: icssg0-eth { + <&main_udmap 0xc107>, /* egress slice 1 */ + + <&main_udmap 0x4100>, /* ingress slice 0 */ +- <&main_udmap 0x4101>, /* ingress slice 1 */ +- <&main_udmap 0x4102>, /* mgmnt rsp slice 0 */ +- <&main_udmap 0x4103>; /* mgmnt rsp slice 1 */ ++ <&main_udmap 0x4101>; /* ingress slice 1 */ + dma-names = "tx0-0", "tx0-1", "tx0-2", "tx0-3", + "tx1-0", "tx1-1", "tx1-2", "tx1-3", + "rx0", "rx1"; +@@ -126,9 +124,7 @@ icssg1_eth: icssg1-eth { + <&main_udmap 0xc207>, /* egress slice 1 */ + + <&main_udmap 0x4200>, /* ingress slice 0 */ +- <&main_udmap 0x4201>, /* ingress slice 1 */ +- <&main_udmap 0x4202>, /* mgmnt rsp slice 0 */ +- <&main_udmap 0x4203>; /* mgmnt rsp slice 1 */ ++ <&main_udmap 0x4201>; /* ingress slice 1 */ + dma-names = "tx0-0", "tx0-1", "tx0-2", "tx0-3", + "tx1-0", "tx1-1", "tx1-2", "tx1-3", + "rx0", "rx1"; +diff --git a/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts b/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts +index a2925555fe8180..fb899c99753ecd 100644 +--- a/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts ++++ b/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts +@@ -123,7 +123,7 @@ main_r5fss1_core1_memory_region: r5f-memory@a5100000 { + no-map; + }; + +- c66_1_dma_memory_region: c66-dma-memory@a6000000 { ++ c66_0_dma_memory_region: c66-dma-memory@a6000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa6000000 0x00 0x100000>; + no-map; +@@ -135,7 +135,7 @@ c66_0_memory_region: c66-memory@a6100000 { + no-map; + }; + +- c66_0_dma_memory_region: c66-dma-memory@a7000000 { ++ c66_1_dma_memory_region: c66-dma-memory@a7000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa7000000 0x00 0x100000>; + no-map; +diff --git a/arch/arm64/boot/dts/ti/k3-j721e-sk.dts b/arch/arm64/boot/dts/ti/k3-j721e-sk.dts +index 0c4575ad8d7cb0..53156b71e47964 100644 +--- a/arch/arm64/boot/dts/ti/k3-j721e-sk.dts ++++ b/arch/arm64/boot/dts/ti/k3-j721e-sk.dts +@@ -119,7 +119,7 @@ main_r5fss1_core1_memory_region: r5f-memory@a5100000 { + no-map; + }; + +- c66_1_dma_memory_region: c66-dma-memory@a6000000 { ++ c66_0_dma_memory_region: c66-dma-memory@a6000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa6000000 0x00 0x100000>; + no-map; +@@ -131,7 +131,7 @@ c66_0_memory_region: c66-memory@a6100000 { + no-map; + }; + +- c66_0_dma_memory_region: c66-dma-memory@a7000000 { ++ c66_1_dma_memory_region: c66-dma-memory@a7000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa7000000 0x00 0x100000>; + no-map; +diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h +index 5fd7caea441936..5a7dfeb8e8eb55 100644 +--- a/arch/arm64/include/asm/cputype.h ++++ b/arch/arm64/include/asm/cputype.h +@@ -143,6 +143,7 @@ + #define APPLE_CPU_PART_M2_AVALANCHE_MAX 0x039 + + #define AMPERE_CPU_PART_AMPERE1 0xAC3 ++#define AMPERE_CPU_PART_AMPERE1A 0xAC4 + + #define MICROSOFT_CPU_PART_AZURE_COBALT_100 0xD49 /* Based on r0p0 of ARM Neoverse N2 */ + +@@ -212,6 +213,7 @@ + #define MIDR_APPLE_M2_BLIZZARD_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_MAX) + #define MIDR_APPLE_M2_AVALANCHE_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_MAX) + #define MIDR_AMPERE1 MIDR_CPU_MODEL(ARM_CPU_IMP_AMPERE, AMPERE_CPU_PART_AMPERE1) ++#define MIDR_AMPERE1A MIDR_CPU_MODEL(ARM_CPU_IMP_AMPERE, AMPERE_CPU_PART_AMPERE1A) + #define MIDR_MICROSOFT_AZURE_COBALT_100 MIDR_CPU_MODEL(ARM_CPU_IMP_MICROSOFT, MICROSOFT_CPU_PART_AZURE_COBALT_100) + + /* Fujitsu Erratum 010001 affects A64FX 1.0 and 1.1, (v0r0 and v1r0) */ +diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h +index 7abf09df70331c..60f4320e44e5d3 100644 +--- a/arch/arm64/include/asm/esr.h ++++ b/arch/arm64/include/asm/esr.h +@@ -10,63 +10,63 @@ + #include <asm/memory.h> + #include <asm/sysreg.h> + +-#define ESR_ELx_EC_UNKNOWN (0x00) +-#define ESR_ELx_EC_WFx (0x01) ++#define ESR_ELx_EC_UNKNOWN UL(0x00) ++#define ESR_ELx_EC_WFx UL(0x01) + /* Unallocated EC: 0x02 */ +-#define ESR_ELx_EC_CP15_32 (0x03) +-#define ESR_ELx_EC_CP15_64 (0x04) +-#define ESR_ELx_EC_CP14_MR (0x05) +-#define ESR_ELx_EC_CP14_LS (0x06) +-#define ESR_ELx_EC_FP_ASIMD (0x07) +-#define ESR_ELx_EC_CP10_ID (0x08) /* EL2 only */ +-#define ESR_ELx_EC_PAC (0x09) /* EL2 and above */ ++#define ESR_ELx_EC_CP15_32 UL(0x03) ++#define ESR_ELx_EC_CP15_64 UL(0x04) ++#define ESR_ELx_EC_CP14_MR UL(0x05) ++#define ESR_ELx_EC_CP14_LS UL(0x06) ++#define ESR_ELx_EC_FP_ASIMD UL(0x07) ++#define ESR_ELx_EC_CP10_ID UL(0x08) /* EL2 only */ ++#define ESR_ELx_EC_PAC UL(0x09) /* EL2 and above */ + /* Unallocated EC: 0x0A - 0x0B */ +-#define ESR_ELx_EC_CP14_64 (0x0C) +-#define ESR_ELx_EC_BTI (0x0D) +-#define ESR_ELx_EC_ILL (0x0E) ++#define ESR_ELx_EC_CP14_64 UL(0x0C) ++#define ESR_ELx_EC_BTI UL(0x0D) ++#define ESR_ELx_EC_ILL UL(0x0E) + /* Unallocated EC: 0x0F - 0x10 */ +-#define ESR_ELx_EC_SVC32 (0x11) +-#define ESR_ELx_EC_HVC32 (0x12) /* EL2 only */ +-#define ESR_ELx_EC_SMC32 (0x13) /* EL2 and above */ ++#define ESR_ELx_EC_SVC32 UL(0x11) ++#define ESR_ELx_EC_HVC32 UL(0x12) /* EL2 only */ ++#define ESR_ELx_EC_SMC32 UL(0x13) /* EL2 and above */ + /* Unallocated EC: 0x14 */ +-#define ESR_ELx_EC_SVC64 (0x15) +-#define ESR_ELx_EC_HVC64 (0x16) /* EL2 and above */ +-#define ESR_ELx_EC_SMC64 (0x17) /* EL2 and above */ +-#define ESR_ELx_EC_SYS64 (0x18) +-#define ESR_ELx_EC_SVE (0x19) +-#define ESR_ELx_EC_ERET (0x1a) /* EL2 only */ ++#define ESR_ELx_EC_SVC64 UL(0x15) ++#define ESR_ELx_EC_HVC64 UL(0x16) /* EL2 and above */ ++#define ESR_ELx_EC_SMC64 UL(0x17) /* EL2 and above */ ++#define ESR_ELx_EC_SYS64 UL(0x18) ++#define ESR_ELx_EC_SVE UL(0x19) ++#define ESR_ELx_EC_ERET UL(0x1a) /* EL2 only */ + /* Unallocated EC: 0x1B */ +-#define ESR_ELx_EC_FPAC (0x1C) /* EL1 and above */ +-#define ESR_ELx_EC_SME (0x1D) ++#define ESR_ELx_EC_FPAC UL(0x1C) /* EL1 and above */ ++#define ESR_ELx_EC_SME UL(0x1D) + /* Unallocated EC: 0x1E */ +-#define ESR_ELx_EC_IMP_DEF (0x1f) /* EL3 only */ +-#define ESR_ELx_EC_IABT_LOW (0x20) +-#define ESR_ELx_EC_IABT_CUR (0x21) +-#define ESR_ELx_EC_PC_ALIGN (0x22) ++#define ESR_ELx_EC_IMP_DEF UL(0x1f) /* EL3 only */ ++#define ESR_ELx_EC_IABT_LOW UL(0x20) ++#define ESR_ELx_EC_IABT_CUR UL(0x21) ++#define ESR_ELx_EC_PC_ALIGN UL(0x22) + /* Unallocated EC: 0x23 */ +-#define ESR_ELx_EC_DABT_LOW (0x24) +-#define ESR_ELx_EC_DABT_CUR (0x25) +-#define ESR_ELx_EC_SP_ALIGN (0x26) +-#define ESR_ELx_EC_MOPS (0x27) +-#define ESR_ELx_EC_FP_EXC32 (0x28) ++#define ESR_ELx_EC_DABT_LOW UL(0x24) ++#define ESR_ELx_EC_DABT_CUR UL(0x25) ++#define ESR_ELx_EC_SP_ALIGN UL(0x26) ++#define ESR_ELx_EC_MOPS UL(0x27) ++#define ESR_ELx_EC_FP_EXC32 UL(0x28) + /* Unallocated EC: 0x29 - 0x2B */ +-#define ESR_ELx_EC_FP_EXC64 (0x2C) ++#define ESR_ELx_EC_FP_EXC64 UL(0x2C) + /* Unallocated EC: 0x2D - 0x2E */ +-#define ESR_ELx_EC_SERROR (0x2F) +-#define ESR_ELx_EC_BREAKPT_LOW (0x30) +-#define ESR_ELx_EC_BREAKPT_CUR (0x31) +-#define ESR_ELx_EC_SOFTSTP_LOW (0x32) +-#define ESR_ELx_EC_SOFTSTP_CUR (0x33) +-#define ESR_ELx_EC_WATCHPT_LOW (0x34) +-#define ESR_ELx_EC_WATCHPT_CUR (0x35) ++#define ESR_ELx_EC_SERROR UL(0x2F) ++#define ESR_ELx_EC_BREAKPT_LOW UL(0x30) ++#define ESR_ELx_EC_BREAKPT_CUR UL(0x31) ++#define ESR_ELx_EC_SOFTSTP_LOW UL(0x32) ++#define ESR_ELx_EC_SOFTSTP_CUR UL(0x33) ++#define ESR_ELx_EC_WATCHPT_LOW UL(0x34) ++#define ESR_ELx_EC_WATCHPT_CUR UL(0x35) + /* Unallocated EC: 0x36 - 0x37 */ +-#define ESR_ELx_EC_BKPT32 (0x38) ++#define ESR_ELx_EC_BKPT32 UL(0x38) + /* Unallocated EC: 0x39 */ +-#define ESR_ELx_EC_VECTOR32 (0x3A) /* EL2 only */ ++#define ESR_ELx_EC_VECTOR32 UL(0x3A) /* EL2 only */ + /* Unallocated EC: 0x3B */ +-#define ESR_ELx_EC_BRK64 (0x3C) ++#define ESR_ELx_EC_BRK64 UL(0x3C) + /* Unallocated EC: 0x3D - 0x3F */ +-#define ESR_ELx_EC_MAX (0x3F) ++#define ESR_ELx_EC_MAX UL(0x3F) + + #define ESR_ELx_EC_SHIFT (26) + #define ESR_ELx_EC_WIDTH (6) +diff --git a/arch/arm64/include/uapi/asm/sigcontext.h b/arch/arm64/include/uapi/asm/sigcontext.h +index 8a45b7a411e045..57f76d82077ea5 100644 +--- a/arch/arm64/include/uapi/asm/sigcontext.h ++++ b/arch/arm64/include/uapi/asm/sigcontext.h +@@ -320,10 +320,10 @@ struct zt_context { + ((sizeof(struct za_context) + (__SVE_VQ_BYTES - 1)) \ + / __SVE_VQ_BYTES * __SVE_VQ_BYTES) + +-#define ZA_SIG_REGS_SIZE(vq) ((vq * __SVE_VQ_BYTES) * (vq * __SVE_VQ_BYTES)) ++#define ZA_SIG_REGS_SIZE(vq) (((vq) * __SVE_VQ_BYTES) * ((vq) * __SVE_VQ_BYTES)) + + #define ZA_SIG_ZAV_OFFSET(vq, n) (ZA_SIG_REGS_OFFSET + \ +- (SVE_SIG_ZREG_SIZE(vq) * n)) ++ (SVE_SIG_ZREG_SIZE(vq) * (n))) + + #define ZA_SIG_CONTEXT_SIZE(vq) \ + (ZA_SIG_REGS_OFFSET + ZA_SIG_REGS_SIZE(vq)) +@@ -334,7 +334,7 @@ struct zt_context { + + #define ZT_SIG_REGS_OFFSET sizeof(struct zt_context) + +-#define ZT_SIG_REGS_SIZE(n) (ZT_SIG_REG_BYTES * n) ++#define ZT_SIG_REGS_SIZE(n) (ZT_SIG_REG_BYTES * (n)) + + #define ZT_SIG_CONTEXT_SIZE(n) \ + (sizeof(struct zt_context) + ZT_SIG_REGS_SIZE(n)) +diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c +index f6b6b450735715..dfefbdf4073a6a 100644 +--- a/arch/arm64/kernel/cpu_errata.c ++++ b/arch/arm64/kernel/cpu_errata.c +@@ -456,6 +456,14 @@ static const struct midr_range erratum_spec_ssbs_list[] = { + }; + #endif + ++#ifdef CONFIG_AMPERE_ERRATUM_AC03_CPU_38 ++static const struct midr_range erratum_ac03_cpu_38_list[] = { ++ MIDR_ALL_VERSIONS(MIDR_AMPERE1), ++ MIDR_ALL_VERSIONS(MIDR_AMPERE1A), ++ {}, ++}; ++#endif ++ + const struct arm64_cpu_capabilities arm64_errata[] = { + #ifdef CONFIG_ARM64_WORKAROUND_CLEAN_CACHE + { +@@ -772,7 +780,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = { + { + .desc = "AmpereOne erratum AC03_CPU_38", + .capability = ARM64_WORKAROUND_AMPERE_AC03_CPU_38, +- ERRATA_MIDR_ALL_VERSIONS(MIDR_AMPERE1), ++ ERRATA_MIDR_RANGE_LIST(erratum_ac03_cpu_38_list), + }, + #endif + { +diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c +index 05688f6a275f10..d36b9160e9346b 100644 +--- a/arch/arm64/kernel/smp.c ++++ b/arch/arm64/kernel/smp.c +@@ -71,7 +71,7 @@ enum ipi_msg_type { + IPI_RESCHEDULE, + IPI_CALL_FUNC, + IPI_CPU_STOP, +- IPI_CPU_CRASH_STOP, ++ IPI_CPU_STOP_NMI, + IPI_TIMER, + IPI_IRQ_WORK, + NR_IPI, +@@ -88,6 +88,8 @@ static int ipi_irq_base __ro_after_init; + static int nr_ipi __ro_after_init = NR_IPI; + static struct irq_desc *ipi_desc[MAX_IPI] __ro_after_init; + ++static bool crash_stop; ++ + static void ipi_setup(int cpu); + + #ifdef CONFIG_HOTPLUG_CPU +@@ -773,7 +775,7 @@ static const char *ipi_types[MAX_IPI] __tracepoint_string = { + [IPI_RESCHEDULE] = "Rescheduling interrupts", + [IPI_CALL_FUNC] = "Function call interrupts", + [IPI_CPU_STOP] = "CPU stop interrupts", +- [IPI_CPU_CRASH_STOP] = "CPU stop (for crash dump) interrupts", ++ [IPI_CPU_STOP_NMI] = "CPU stop NMIs", + [IPI_TIMER] = "Timer broadcast interrupts", + [IPI_IRQ_WORK] = "IRQ work interrupts", + [IPI_CPU_BACKTRACE] = "CPU backtrace interrupts", +@@ -817,9 +819,9 @@ void arch_irq_work_raise(void) + } + #endif + +-static void __noreturn local_cpu_stop(void) ++static void __noreturn local_cpu_stop(unsigned int cpu) + { +- set_cpu_online(smp_processor_id(), false); ++ set_cpu_online(cpu, false); + + local_daif_mask(); + sdei_mask_local_cpu(); +@@ -833,21 +835,26 @@ static void __noreturn local_cpu_stop(void) + */ + void __noreturn panic_smp_self_stop(void) + { +- local_cpu_stop(); ++ local_cpu_stop(smp_processor_id()); + } + +-#ifdef CONFIG_KEXEC_CORE +-static atomic_t waiting_for_crash_ipi = ATOMIC_INIT(0); +-#endif +- + static void __noreturn ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs) + { + #ifdef CONFIG_KEXEC_CORE ++ /* ++ * Use local_daif_mask() instead of local_irq_disable() to make sure ++ * that pseudo-NMIs are disabled. The "crash stop" code starts with ++ * an IRQ and falls back to NMI (which might be pseudo). If the IRQ ++ * finally goes through right as we're timing out then the NMI could ++ * interrupt us. It's better to prevent the NMI and let the IRQ ++ * finish since the pt_regs will be better. ++ */ ++ local_daif_mask(); ++ + crash_save_cpu(regs, cpu); + +- atomic_dec(&waiting_for_crash_ipi); ++ set_cpu_online(cpu, false); + +- local_irq_disable(); + sdei_mask_local_cpu(); + + if (IS_ENABLED(CONFIG_HOTPLUG_CPU)) +@@ -912,14 +919,12 @@ static void do_handle_IPI(int ipinr) + break; + + case IPI_CPU_STOP: +- local_cpu_stop(); +- break; +- +- case IPI_CPU_CRASH_STOP: +- if (IS_ENABLED(CONFIG_KEXEC_CORE)) { ++ case IPI_CPU_STOP_NMI: ++ if (IS_ENABLED(CONFIG_KEXEC_CORE) && crash_stop) { + ipi_cpu_crash_stop(cpu, get_irq_regs()); +- + unreachable(); ++ } else { ++ local_cpu_stop(cpu); + } + break; + +@@ -974,8 +979,7 @@ static bool ipi_should_be_nmi(enum ipi_msg_type ipi) + return false; + + switch (ipi) { +- case IPI_CPU_STOP: +- case IPI_CPU_CRASH_STOP: ++ case IPI_CPU_STOP_NMI: + case IPI_CPU_BACKTRACE: + case IPI_KGDB_ROUNDUP: + return true; +@@ -1088,79 +1092,109 @@ static inline unsigned int num_other_online_cpus(void) + + void smp_send_stop(void) + { ++ static unsigned long stop_in_progress; ++ cpumask_t mask; + unsigned long timeout; + +- if (num_other_online_cpus()) { +- cpumask_t mask; ++ /* ++ * If this cpu is the only one alive at this point in time, online or ++ * not, there are no stop messages to be sent around, so just back out. ++ */ ++ if (num_other_online_cpus() == 0) ++ goto skip_ipi; + +- cpumask_copy(&mask, cpu_online_mask); +- cpumask_clear_cpu(smp_processor_id(), &mask); ++ /* Only proceed if this is the first CPU to reach this code */ ++ if (test_and_set_bit(0, &stop_in_progress)) ++ return; + +- if (system_state <= SYSTEM_RUNNING) +- pr_crit("SMP: stopping secondary CPUs\n"); +- smp_cross_call(&mask, IPI_CPU_STOP); +- } ++ /* ++ * Send an IPI to all currently online CPUs except the CPU running ++ * this code. ++ * ++ * NOTE: we don't do anything here to prevent other CPUs from coming ++ * online after we snapshot `cpu_online_mask`. Ideally, the calling code ++ * should do something to prevent other CPUs from coming up. This code ++ * can be called in the panic path and thus it doesn't seem wise to ++ * grab the CPU hotplug mutex ourselves. Worst case: ++ * - If a CPU comes online as we're running, we'll likely notice it ++ * during the 1 second wait below and then we'll catch it when we try ++ * with an NMI (assuming NMIs are enabled) since we re-snapshot the ++ * mask before sending an NMI. ++ * - If we leave the function and see that CPUs are still online we'll ++ * at least print a warning. Especially without NMIs this function ++ * isn't foolproof anyway so calling code will just have to accept ++ * the fact that there could be cases where a CPU can't be stopped. ++ */ ++ cpumask_copy(&mask, cpu_online_mask); ++ cpumask_clear_cpu(smp_processor_id(), &mask); + +- /* Wait up to one second for other CPUs to stop */ ++ if (system_state <= SYSTEM_RUNNING) ++ pr_crit("SMP: stopping secondary CPUs\n"); ++ ++ /* ++ * Start with a normal IPI and wait up to one second for other CPUs to ++ * stop. We do this first because it gives other processors a chance ++ * to exit critical sections / drop locks and makes the rest of the ++ * stop process (especially console flush) more robust. ++ */ ++ smp_cross_call(&mask, IPI_CPU_STOP); + timeout = USEC_PER_SEC; + while (num_other_online_cpus() && timeout--) + udelay(1); + +- if (num_other_online_cpus()) ++ /* ++ * If CPUs are still online, try an NMI. There's no excuse for this to ++ * be slow, so we only give them an extra 10 ms to respond. ++ */ ++ if (num_other_online_cpus() && ipi_should_be_nmi(IPI_CPU_STOP_NMI)) { ++ smp_rmb(); ++ cpumask_copy(&mask, cpu_online_mask); ++ cpumask_clear_cpu(smp_processor_id(), &mask); ++ ++ pr_info("SMP: retry stop with NMI for CPUs %*pbl\n", ++ cpumask_pr_args(&mask)); ++ ++ smp_cross_call(&mask, IPI_CPU_STOP_NMI); ++ timeout = USEC_PER_MSEC * 10; ++ while (num_other_online_cpus() && timeout--) ++ udelay(1); ++ } ++ ++ if (num_other_online_cpus()) { ++ smp_rmb(); ++ cpumask_copy(&mask, cpu_online_mask); ++ cpumask_clear_cpu(smp_processor_id(), &mask); ++ + pr_warn("SMP: failed to stop secondary CPUs %*pbl\n", +- cpumask_pr_args(cpu_online_mask)); ++ cpumask_pr_args(&mask)); ++ } + ++skip_ipi: + sdei_mask_local_cpu(); + } + + #ifdef CONFIG_KEXEC_CORE + void crash_smp_send_stop(void) + { +- static int cpus_stopped; +- cpumask_t mask; +- unsigned long timeout; +- + /* + * This function can be called twice in panic path, but obviously + * we execute this only once. ++ * ++ * We use this same boolean to tell whether the IPI we send was a ++ * stop or a "crash stop". + */ +- if (cpus_stopped) ++ if (crash_stop) + return; ++ crash_stop = 1; + +- cpus_stopped = 1; ++ smp_send_stop(); + +- /* +- * If this cpu is the only one alive at this point in time, online or +- * not, there are no stop messages to be sent around, so just back out. +- */ +- if (num_other_online_cpus() == 0) +- goto skip_ipi; +- +- cpumask_copy(&mask, cpu_online_mask); +- cpumask_clear_cpu(smp_processor_id(), &mask); +- +- atomic_set(&waiting_for_crash_ipi, num_other_online_cpus()); +- +- pr_crit("SMP: stopping secondary CPUs\n"); +- smp_cross_call(&mask, IPI_CPU_CRASH_STOP); +- +- /* Wait up to one second for other CPUs to stop */ +- timeout = USEC_PER_SEC; +- while ((atomic_read(&waiting_for_crash_ipi) > 0) && timeout--) +- udelay(1); +- +- if (atomic_read(&waiting_for_crash_ipi) > 0) +- pr_warn("SMP: failed to stop secondary CPUs %*pbl\n", +- cpumask_pr_args(&mask)); +- +-skip_ipi: +- sdei_mask_local_cpu(); + sdei_handler_abort(); + } + + bool smp_crash_stop_failed(void) + { +- return (atomic_read(&waiting_for_crash_ipi) > 0); ++ return num_other_online_cpus() != 0; + } + #endif + +diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c +index efb053af331cc9..f26ae1819d1b4c 100644 +--- a/arch/arm64/kvm/hyp/nvhe/ffa.c ++++ b/arch/arm64/kvm/hyp/nvhe/ffa.c +@@ -423,9 +423,9 @@ static void do_ffa_mem_frag_tx(struct arm_smccc_res *res, + return; + } + +-static __always_inline void do_ffa_mem_xfer(const u64 func_id, +- struct arm_smccc_res *res, +- struct kvm_cpu_context *ctxt) ++static void __do_ffa_mem_xfer(const u64 func_id, ++ struct arm_smccc_res *res, ++ struct kvm_cpu_context *ctxt) + { + DECLARE_REG(u32, len, ctxt, 1); + DECLARE_REG(u32, fraglen, ctxt, 2); +@@ -437,9 +437,6 @@ static __always_inline void do_ffa_mem_xfer(const u64 func_id, + u32 offset, nr_ranges; + int ret = 0; + +- BUILD_BUG_ON(func_id != FFA_FN64_MEM_SHARE && +- func_id != FFA_FN64_MEM_LEND); +- + if (addr_mbz || npages_mbz || fraglen > len || + fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) { + ret = FFA_RET_INVALID_PARAMETERS; +@@ -458,6 +455,11 @@ static __always_inline void do_ffa_mem_xfer(const u64 func_id, + goto out_unlock; + } + ++ if (len > ffa_desc_buf.len) { ++ ret = FFA_RET_NO_MEMORY; ++ goto out_unlock; ++ } ++ + buf = hyp_buffers.tx; + memcpy(buf, host_buffers.tx, fraglen); + +@@ -509,6 +511,13 @@ static __always_inline void do_ffa_mem_xfer(const u64 func_id, + goto out_unlock; + } + ++#define do_ffa_mem_xfer(fid, res, ctxt) \ ++ do { \ ++ BUILD_BUG_ON((fid) != FFA_FN64_MEM_SHARE && \ ++ (fid) != FFA_FN64_MEM_LEND); \ ++ __do_ffa_mem_xfer((fid), (res), (ctxt)); \ ++ } while (0); ++ + static void do_ffa_mem_reclaim(struct arm_smccc_res *res, + struct kvm_cpu_context *ctxt) + { +diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c +index 1bf483ec971d92..c4190865f24335 100644 +--- a/arch/arm64/net/bpf_jit_comp.c ++++ b/arch/arm64/net/bpf_jit_comp.c +@@ -26,7 +26,7 @@ + + #define TMP_REG_1 (MAX_BPF_JIT_REG + 0) + #define TMP_REG_2 (MAX_BPF_JIT_REG + 1) +-#define TCALL_CNT (MAX_BPF_JIT_REG + 2) ++#define TCCNT_PTR (MAX_BPF_JIT_REG + 2) + #define TMP_REG_3 (MAX_BPF_JIT_REG + 3) + #define FP_BOTTOM (MAX_BPF_JIT_REG + 4) + #define ARENA_VM_START (MAX_BPF_JIT_REG + 5) +@@ -63,8 +63,8 @@ static const int bpf2a64[] = { + [TMP_REG_1] = A64_R(10), + [TMP_REG_2] = A64_R(11), + [TMP_REG_3] = A64_R(12), +- /* tail_call_cnt */ +- [TCALL_CNT] = A64_R(26), ++ /* tail_call_cnt_ptr */ ++ [TCCNT_PTR] = A64_R(26), + /* temporary register for blinding constants */ + [BPF_REG_AX] = A64_R(9), + [FP_BOTTOM] = A64_R(27), +@@ -282,13 +282,35 @@ static bool is_lsi_offset(int offset, int scale) + * mov x29, sp + * stp x19, x20, [sp, #-16]! + * stp x21, x22, [sp, #-16]! +- * stp x25, x26, [sp, #-16]! ++ * stp x26, x25, [sp, #-16]! ++ * stp x26, x25, [sp, #-16]! + * stp x27, x28, [sp, #-16]! + * mov x25, sp + * mov tcc, #0 + * // PROLOGUE_OFFSET + */ + ++static void prepare_bpf_tail_call_cnt(struct jit_ctx *ctx) ++{ ++ const struct bpf_prog *prog = ctx->prog; ++ const bool is_main_prog = !bpf_is_subprog(prog); ++ const u8 ptr = bpf2a64[TCCNT_PTR]; ++ const u8 fp = bpf2a64[BPF_REG_FP]; ++ const u8 tcc = ptr; ++ ++ emit(A64_PUSH(ptr, fp, A64_SP), ctx); ++ if (is_main_prog) { ++ /* Initialize tail_call_cnt. */ ++ emit(A64_MOVZ(1, tcc, 0, 0), ctx); ++ emit(A64_PUSH(tcc, fp, A64_SP), ctx); ++ emit(A64_MOV(1, ptr, A64_SP), ctx); ++ } else { ++ emit(A64_PUSH(ptr, fp, A64_SP), ctx); ++ emit(A64_NOP, ctx); ++ emit(A64_NOP, ctx); ++ } ++} ++ + #define BTI_INSNS (IS_ENABLED(CONFIG_ARM64_BTI_KERNEL) ? 1 : 0) + #define PAC_INSNS (IS_ENABLED(CONFIG_ARM64_PTR_AUTH_KERNEL) ? 1 : 0) + +@@ -296,7 +318,7 @@ static bool is_lsi_offset(int offset, int scale) + #define POKE_OFFSET (BTI_INSNS + 1) + + /* Tail call offset to jump into */ +-#define PROLOGUE_OFFSET (BTI_INSNS + 2 + PAC_INSNS + 8) ++#define PROLOGUE_OFFSET (BTI_INSNS + 2 + PAC_INSNS + 10) + + static int build_prologue(struct jit_ctx *ctx, bool ebpf_from_cbpf, + bool is_exception_cb, u64 arena_vm_start) +@@ -308,7 +330,6 @@ static int build_prologue(struct jit_ctx *ctx, bool ebpf_from_cbpf, + const u8 r8 = bpf2a64[BPF_REG_8]; + const u8 r9 = bpf2a64[BPF_REG_9]; + const u8 fp = bpf2a64[BPF_REG_FP]; +- const u8 tcc = bpf2a64[TCALL_CNT]; + const u8 fpb = bpf2a64[FP_BOTTOM]; + const u8 arena_vm_base = bpf2a64[ARENA_VM_START]; + const int idx0 = ctx->idx; +@@ -359,7 +380,7 @@ static int build_prologue(struct jit_ctx *ctx, bool ebpf_from_cbpf, + /* Save callee-saved registers */ + emit(A64_PUSH(r6, r7, A64_SP), ctx); + emit(A64_PUSH(r8, r9, A64_SP), ctx); +- emit(A64_PUSH(fp, tcc, A64_SP), ctx); ++ prepare_bpf_tail_call_cnt(ctx); + emit(A64_PUSH(fpb, A64_R(28), A64_SP), ctx); + } else { + /* +@@ -372,18 +393,15 @@ static int build_prologue(struct jit_ctx *ctx, bool ebpf_from_cbpf, + * callee-saved registers. The exception callback will not push + * anything and re-use the main program's stack. + * +- * 10 registers are on the stack ++ * 12 registers are on the stack + */ +- emit(A64_SUB_I(1, A64_SP, A64_FP, 80), ctx); ++ emit(A64_SUB_I(1, A64_SP, A64_FP, 96), ctx); + } + + /* Set up BPF prog stack base register */ + emit(A64_MOV(1, fp, A64_SP), ctx); + + if (!ebpf_from_cbpf && is_main_prog) { +- /* Initialize tail_call_cnt */ +- emit(A64_MOVZ(1, tcc, 0, 0), ctx); +- + cur_offset = ctx->idx - idx0; + if (cur_offset != PROLOGUE_OFFSET) { + pr_err_once("PROLOGUE_OFFSET = %d, expected %d!\n", +@@ -432,7 +450,8 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx) + + const u8 tmp = bpf2a64[TMP_REG_1]; + const u8 prg = bpf2a64[TMP_REG_2]; +- const u8 tcc = bpf2a64[TCALL_CNT]; ++ const u8 tcc = bpf2a64[TMP_REG_3]; ++ const u8 ptr = bpf2a64[TCCNT_PTR]; + const int idx0 = ctx->idx; + #define cur_offset (ctx->idx - idx0) + #define jmp_offset (out_offset - (cur_offset)) +@@ -449,11 +468,12 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx) + emit(A64_B_(A64_COND_CS, jmp_offset), ctx); + + /* +- * if (tail_call_cnt >= MAX_TAIL_CALL_CNT) ++ * if ((*tail_call_cnt_ptr) >= MAX_TAIL_CALL_CNT) + * goto out; +- * tail_call_cnt++; ++ * (*tail_call_cnt_ptr)++; + */ + emit_a64_mov_i64(tmp, MAX_TAIL_CALL_CNT, ctx); ++ emit(A64_LDR64I(tcc, ptr, 0), ctx); + emit(A64_CMP(1, tcc, tmp), ctx); + emit(A64_B_(A64_COND_CS, jmp_offset), ctx); + emit(A64_ADD_I(1, tcc, tcc, 1), ctx); +@@ -469,6 +489,9 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx) + emit(A64_LDR64(prg, tmp, prg), ctx); + emit(A64_CBZ(1, prg, jmp_offset), ctx); + ++ /* Update tail_call_cnt if the slot is populated. */ ++ emit(A64_STR64I(tcc, ptr, 0), ctx); ++ + /* goto *(prog->bpf_func + prologue_offset); */ + off = offsetof(struct bpf_prog, bpf_func); + emit_a64_mov_i64(tmp, off, ctx); +@@ -721,6 +744,7 @@ static void build_epilogue(struct jit_ctx *ctx, bool is_exception_cb) + const u8 r8 = bpf2a64[BPF_REG_8]; + const u8 r9 = bpf2a64[BPF_REG_9]; + const u8 fp = bpf2a64[BPF_REG_FP]; ++ const u8 ptr = bpf2a64[TCCNT_PTR]; + const u8 fpb = bpf2a64[FP_BOTTOM]; + + /* We're done with BPF stack */ +@@ -738,7 +762,8 @@ static void build_epilogue(struct jit_ctx *ctx, bool is_exception_cb) + /* Restore x27 and x28 */ + emit(A64_POP(fpb, A64_R(28), A64_SP), ctx); + /* Restore fs (x25) and x26 */ +- emit(A64_POP(fp, A64_R(26), A64_SP), ctx); ++ emit(A64_POP(ptr, fp, A64_SP), ctx); ++ emit(A64_POP(ptr, fp, A64_SP), ctx); + + /* Restore callee-saved register */ + emit(A64_POP(r8, r9, A64_SP), ctx); +diff --git a/arch/loongarch/include/asm/kvm_vcpu.h b/arch/loongarch/include/asm/kvm_vcpu.h +index d741c3e9933a51..590a92cb54165c 100644 +--- a/arch/loongarch/include/asm/kvm_vcpu.h ++++ b/arch/loongarch/include/asm/kvm_vcpu.h +@@ -76,6 +76,7 @@ static inline void kvm_restore_lasx(struct loongarch_fpu *fpu) { } + #endif + + void kvm_init_timer(struct kvm_vcpu *vcpu, unsigned long hz); ++void kvm_reset_timer(struct kvm_vcpu *vcpu); + void kvm_save_timer(struct kvm_vcpu *vcpu); + void kvm_restore_timer(struct kvm_vcpu *vcpu); + +diff --git a/arch/loongarch/kvm/timer.c b/arch/loongarch/kvm/timer.c +index 74a4b5c272d60e..bcc6b6d063d914 100644 +--- a/arch/loongarch/kvm/timer.c ++++ b/arch/loongarch/kvm/timer.c +@@ -188,3 +188,10 @@ void kvm_save_timer(struct kvm_vcpu *vcpu) + kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ESTAT); + preempt_enable(); + } ++ ++void kvm_reset_timer(struct kvm_vcpu *vcpu) ++{ ++ write_gcsr_timercfg(0); ++ kvm_write_sw_gcsr(vcpu->arch.csr, LOONGARCH_CSR_TCFG, 0); ++ hrtimer_cancel(&vcpu->arch.swtimer); ++} +diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c +index 0b53f4d9fddf91..9e8030d4512902 100644 +--- a/arch/loongarch/kvm/vcpu.c ++++ b/arch/loongarch/kvm/vcpu.c +@@ -572,7 +572,7 @@ static int kvm_set_one_reg(struct kvm_vcpu *vcpu, + vcpu->kvm->arch.time_offset = (signed long)(v - drdtime()); + break; + case KVM_REG_LOONGARCH_VCPU_RESET: +- vcpu->arch.st.guest_addr = 0; ++ kvm_reset_timer(vcpu); + memset(&vcpu->arch.irq_pending, 0, sizeof(vcpu->arch.irq_pending)); + memset(&vcpu->arch.irq_clear, 0, sizeof(vcpu->arch.irq_clear)); + break; +diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c +index 2584e94e213468..fda7eac23f872d 100644 +--- a/arch/m68k/kernel/process.c ++++ b/arch/m68k/kernel/process.c +@@ -117,7 +117,7 @@ asmlinkage int m68k_clone(struct pt_regs *regs) + { + /* regs will be equal to current_pt_regs() */ + struct kernel_clone_args args = { +- .flags = regs->d1 & ~CSIGNAL, ++ .flags = (u32)(regs->d1) & ~CSIGNAL, + .pidfd = (int __user *)regs->d3, + .child_tid = (int __user *)regs->d4, + .parent_tid = (int __user *)regs->d3, +diff --git a/arch/powerpc/crypto/Kconfig b/arch/powerpc/crypto/Kconfig +index 1e201b7ae2fc60..bd9d77b0c92ec1 100644 +--- a/arch/powerpc/crypto/Kconfig ++++ b/arch/powerpc/crypto/Kconfig +@@ -96,6 +96,7 @@ config CRYPTO_AES_PPC_SPE + + config CRYPTO_AES_GCM_P10 + tristate "Stitched AES/GCM acceleration support on P10 or later CPU (PPC)" ++ depends on BROKEN + depends on PPC64 && CPU_LITTLE_ENDIAN && VSX + select CRYPTO_LIB_AES + select CRYPTO_ALGAPI +diff --git a/arch/powerpc/include/asm/asm-compat.h b/arch/powerpc/include/asm/asm-compat.h +index 2bc53c646ccd7d..83848b534cb171 100644 +--- a/arch/powerpc/include/asm/asm-compat.h ++++ b/arch/powerpc/include/asm/asm-compat.h +@@ -39,6 +39,12 @@ + #define STDX_BE stringify_in_c(stdbrx) + #endif + ++#ifdef CONFIG_CC_IS_CLANG ++#define DS_FORM_CONSTRAINT "Z<>" ++#else ++#define DS_FORM_CONSTRAINT "YZ<>" ++#endif ++ + #else /* 32-bit */ + + /* operations for longs and pointers */ +diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h +index 5bf6a4d49268c7..d1ea554c33ed7e 100644 +--- a/arch/powerpc/include/asm/atomic.h ++++ b/arch/powerpc/include/asm/atomic.h +@@ -11,6 +11,7 @@ + #include <asm/cmpxchg.h> + #include <asm/barrier.h> + #include <asm/asm-const.h> ++#include <asm/asm-compat.h> + + /* + * Since *_return_relaxed and {cmp}xchg_relaxed are implemented with +@@ -197,7 +198,7 @@ static __inline__ s64 arch_atomic64_read(const atomic64_t *v) + if (IS_ENABLED(CONFIG_PPC_KERNEL_PREFIXED)) + __asm__ __volatile__("ld %0,0(%1)" : "=r"(t) : "b"(&v->counter)); + else +- __asm__ __volatile__("ld%U1%X1 %0,%1" : "=r"(t) : "m<>"(v->counter)); ++ __asm__ __volatile__("ld%U1%X1 %0,%1" : "=r"(t) : DS_FORM_CONSTRAINT (v->counter)); + + return t; + } +@@ -208,7 +209,7 @@ static __inline__ void arch_atomic64_set(atomic64_t *v, s64 i) + if (IS_ENABLED(CONFIG_PPC_KERNEL_PREFIXED)) + __asm__ __volatile__("std %1,0(%2)" : "=m"(v->counter) : "r"(i), "b"(&v->counter)); + else +- __asm__ __volatile__("std%U0%X0 %1,%0" : "=m<>"(v->counter) : "r"(i)); ++ __asm__ __volatile__("std%U0%X0 %1,%0" : "=" DS_FORM_CONSTRAINT (v->counter) : "r"(i)); + } + + #define ATOMIC64_OP(op, asm_op) \ +diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h +index fd594bf6c6a9c5..4f5a46a77fa2b6 100644 +--- a/arch/powerpc/include/asm/uaccess.h ++++ b/arch/powerpc/include/asm/uaccess.h +@@ -6,6 +6,7 @@ + #include <asm/page.h> + #include <asm/extable.h> + #include <asm/kup.h> ++#include <asm/asm-compat.h> + + #ifdef __powerpc64__ + /* We use TASK_SIZE_USER64 as TASK_SIZE is not constant */ +@@ -92,12 +93,6 @@ __pu_failed: \ + : label) + #endif + +-#ifdef CONFIG_CC_IS_CLANG +-#define DS_FORM_CONSTRAINT "Z<>" +-#else +-#define DS_FORM_CONSTRAINT "YZ<>" +-#endif +- + #ifdef __powerpc64__ + #ifdef CONFIG_PPC_KERNEL_PREFIXED + #define __put_user_asm2_goto(x, ptr, label) \ +diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S +index edc479a7c2bce3..0bd317b5647526 100644 +--- a/arch/powerpc/kernel/head_8xx.S ++++ b/arch/powerpc/kernel/head_8xx.S +@@ -41,12 +41,12 @@ + #include "head_32.h" + + .macro compare_to_kernel_boundary scratch, addr +-#if CONFIG_TASK_SIZE <= 0x80000000 && CONFIG_PAGE_OFFSET >= 0x80000000 ++#if CONFIG_TASK_SIZE <= 0x80000000 && MODULES_VADDR >= 0x80000000 + /* By simply checking Address >= 0x80000000, we know if its a kernel address */ + not. \scratch, \addr + #else + rlwinm \scratch, \addr, 16, 0xfff8 +- cmpli cr0, \scratch, PAGE_OFFSET@h ++ cmpli cr0, \scratch, TASK_SIZE@h + #endif + .endm + +@@ -404,7 +404,7 @@ FixupDAR:/* Entry point for dcbx workaround. */ + mfspr r10, SPRN_SRR0 + mtspr SPRN_MD_EPN, r10 + rlwinm r11, r10, 16, 0xfff8 +- cmpli cr1, r11, PAGE_OFFSET@h ++ cmpli cr1, r11, TASK_SIZE@h + mfspr r11, SPRN_M_TWB /* Get level 1 table */ + blt+ cr1, 3f + +diff --git a/arch/powerpc/kernel/vdso/gettimeofday.S b/arch/powerpc/kernel/vdso/gettimeofday.S +index 48fc6658053aa4..894cb939cd2b31 100644 +--- a/arch/powerpc/kernel/vdso/gettimeofday.S ++++ b/arch/powerpc/kernel/vdso/gettimeofday.S +@@ -38,11 +38,7 @@ + .else + addi r4, r5, VDSO_DATA_OFFSET + .endif +-#ifdef __powerpc64__ + bl CFUNC(DOTSYM(\funct)) +-#else +- bl \funct +-#endif + PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1) + #ifdef __powerpc64__ + PPC_LL r2, PPC_MIN_STKFRM + STK_GOT(r1) +diff --git a/arch/powerpc/mm/nohash/8xx.c b/arch/powerpc/mm/nohash/8xx.c +index d93433e26dedb8..e5cc3b3a259f9a 100644 +--- a/arch/powerpc/mm/nohash/8xx.c ++++ b/arch/powerpc/mm/nohash/8xx.c +@@ -154,11 +154,11 @@ unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top) + + mmu_mapin_immr(); + +- mmu_mapin_ram_chunk(0, boundary, PAGE_KERNEL_TEXT, true); ++ mmu_mapin_ram_chunk(0, boundary, PAGE_KERNEL_X, true); + if (debug_pagealloc_enabled_or_kfence()) { + top = boundary; + } else { +- mmu_mapin_ram_chunk(boundary, einittext8, PAGE_KERNEL_TEXT, true); ++ mmu_mapin_ram_chunk(boundary, einittext8, PAGE_KERNEL_X, true); + mmu_mapin_ram_chunk(einittext8, top, PAGE_KERNEL, true); + } + +diff --git a/arch/riscv/include/asm/kvm_vcpu_pmu.h b/arch/riscv/include/asm/kvm_vcpu_pmu.h +index fa0f535bbbf024..1d85b661750884 100644 +--- a/arch/riscv/include/asm/kvm_vcpu_pmu.h ++++ b/arch/riscv/include/asm/kvm_vcpu_pmu.h +@@ -10,6 +10,7 @@ + #define __KVM_VCPU_RISCV_PMU_H + + #include <linux/perf/riscv_pmu.h> ++#include <asm/kvm_vcpu_insn.h> + #include <asm/sbi.h> + + #ifdef CONFIG_RISCV_PMU_SBI +@@ -64,11 +65,11 @@ struct kvm_pmu { + + #if defined(CONFIG_32BIT) + #define KVM_RISCV_VCPU_HPMCOUNTER_CSR_FUNCS \ +-{.base = CSR_CYCLEH, .count = 31, .func = kvm_riscv_vcpu_pmu_read_hpm }, \ +-{.base = CSR_CYCLE, .count = 31, .func = kvm_riscv_vcpu_pmu_read_hpm }, ++{.base = CSR_CYCLEH, .count = 32, .func = kvm_riscv_vcpu_pmu_read_hpm }, \ ++{.base = CSR_CYCLE, .count = 32, .func = kvm_riscv_vcpu_pmu_read_hpm }, + #else + #define KVM_RISCV_VCPU_HPMCOUNTER_CSR_FUNCS \ +-{.base = CSR_CYCLE, .count = 31, .func = kvm_riscv_vcpu_pmu_read_hpm }, ++{.base = CSR_CYCLE, .count = 32, .func = kvm_riscv_vcpu_pmu_read_hpm }, + #endif + + int kvm_riscv_vcpu_pmu_incr_fw(struct kvm_vcpu *vcpu, unsigned long fid); +@@ -104,8 +105,20 @@ void kvm_riscv_vcpu_pmu_reset(struct kvm_vcpu *vcpu); + struct kvm_pmu { + }; + ++static inline int kvm_riscv_vcpu_pmu_read_legacy(struct kvm_vcpu *vcpu, unsigned int csr_num, ++ unsigned long *val, unsigned long new_val, ++ unsigned long wr_mask) ++{ ++ if (csr_num == CSR_CYCLE || csr_num == CSR_INSTRET) { ++ *val = 0; ++ return KVM_INSN_CONTINUE_NEXT_SEPC; ++ } else { ++ return KVM_INSN_ILLEGAL_TRAP; ++ } ++} ++ + #define KVM_RISCV_VCPU_HPMCOUNTER_CSR_FUNCS \ +-{.base = 0, .count = 0, .func = NULL }, ++{.base = CSR_CYCLE, .count = 3, .func = kvm_riscv_vcpu_pmu_read_legacy }, + + static inline void kvm_riscv_vcpu_pmu_init(struct kvm_vcpu *vcpu) {} + static inline int kvm_riscv_vcpu_pmu_incr_fw(struct kvm_vcpu *vcpu, unsigned long fid) +diff --git a/arch/riscv/kernel/perf_callchain.c b/arch/riscv/kernel/perf_callchain.c +index 3348a61de7d998..2932791e938821 100644 +--- a/arch/riscv/kernel/perf_callchain.c ++++ b/arch/riscv/kernel/perf_callchain.c +@@ -62,7 +62,7 @@ void perf_callchain_user(struct perf_callchain_entry_ctx *entry, + perf_callchain_store(entry, regs->epc); + + fp = user_backtrace(entry, fp, regs->ra); +- while (fp && !(fp & 0x3) && entry->nr < entry->max_stack) ++ while (fp && !(fp & 0x7) && entry->nr < entry->max_stack) + fp = user_backtrace(entry, fp, 0); + } + +diff --git a/arch/riscv/kvm/vcpu_pmu.c b/arch/riscv/kvm/vcpu_pmu.c +index bcf41d6e0df0e3..2707a51b082ca7 100644 +--- a/arch/riscv/kvm/vcpu_pmu.c ++++ b/arch/riscv/kvm/vcpu_pmu.c +@@ -391,19 +391,9 @@ int kvm_riscv_vcpu_pmu_read_hpm(struct kvm_vcpu *vcpu, unsigned int csr_num, + static void kvm_pmu_clear_snapshot_area(struct kvm_vcpu *vcpu) + { + struct kvm_pmu *kvpmu = vcpu_to_pmu(vcpu); +- int snapshot_area_size = sizeof(struct riscv_pmu_snapshot_data); + +- if (kvpmu->sdata) { +- if (kvpmu->snapshot_addr != INVALID_GPA) { +- memset(kvpmu->sdata, 0, snapshot_area_size); +- kvm_vcpu_write_guest(vcpu, kvpmu->snapshot_addr, +- kvpmu->sdata, snapshot_area_size); +- } else { +- pr_warn("snapshot address invalid\n"); +- } +- kfree(kvpmu->sdata); +- kvpmu->sdata = NULL; +- } ++ kfree(kvpmu->sdata); ++ kvpmu->sdata = NULL; + kvpmu->snapshot_addr = INVALID_GPA; + } + +diff --git a/arch/riscv/kvm/vcpu_sbi.c b/arch/riscv/kvm/vcpu_sbi.c +index 62f409d4176e41..7de128be8db9bc 100644 +--- a/arch/riscv/kvm/vcpu_sbi.c ++++ b/arch/riscv/kvm/vcpu_sbi.c +@@ -127,8 +127,8 @@ void kvm_riscv_vcpu_sbi_forward(struct kvm_vcpu *vcpu, struct kvm_run *run) + run->riscv_sbi.args[3] = cp->a3; + run->riscv_sbi.args[4] = cp->a4; + run->riscv_sbi.args[5] = cp->a5; +- run->riscv_sbi.ret[0] = cp->a0; +- run->riscv_sbi.ret[1] = cp->a1; ++ run->riscv_sbi.ret[0] = SBI_ERR_NOT_SUPPORTED; ++ run->riscv_sbi.ret[1] = 0; + } + + void kvm_riscv_vcpu_sbi_system_reset(struct kvm_vcpu *vcpu, +diff --git a/arch/s390/include/asm/ftrace.h b/arch/s390/include/asm/ftrace.h +index 77e479d44f1e37..d0cb3ecd63908a 100644 +--- a/arch/s390/include/asm/ftrace.h ++++ b/arch/s390/include/asm/ftrace.h +@@ -7,8 +7,23 @@ + #define MCOUNT_INSN_SIZE 6 + + #ifndef __ASSEMBLY__ ++#include <asm/stacktrace.h> + +-unsigned long return_address(unsigned int n); ++static __always_inline unsigned long return_address(unsigned int n) ++{ ++ struct stack_frame *sf; ++ ++ if (!n) ++ return (unsigned long)__builtin_return_address(0); ++ ++ sf = (struct stack_frame *)current_frame_address(); ++ do { ++ sf = (struct stack_frame *)sf->back_chain; ++ if (!sf) ++ return 0; ++ } while (--n); ++ return sf->gprs[8]; ++} + #define ftrace_return_address(n) return_address(n) + + void ftrace_caller(void); +diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c +index 640363b2a1059e..9f59837d159e0c 100644 +--- a/arch/s390/kernel/stacktrace.c ++++ b/arch/s390/kernel/stacktrace.c +@@ -162,22 +162,3 @@ void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie, + { + arch_stack_walk_user_common(consume_entry, cookie, NULL, regs, false); + } +- +-unsigned long return_address(unsigned int n) +-{ +- struct unwind_state state; +- unsigned long addr; +- +- /* Increment to skip current stack entry */ +- n++; +- +- unwind_for_each_frame(&state, NULL, NULL, 0) { +- addr = unwind_get_return_address(&state); +- if (!addr) +- break; +- if (!n--) +- return addr; +- } +- return 0; +-} +-EXPORT_SYMBOL_GPL(return_address); +diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c +index 8fe4c2b07128e7..327c45c5013fea 100644 +--- a/arch/x86/coco/tdx/tdx.c ++++ b/arch/x86/coco/tdx/tdx.c +@@ -7,6 +7,7 @@ + #include <linux/cpufeature.h> + #include <linux/export.h> + #include <linux/io.h> ++#include <linux/kexec.h> + #include <asm/coco.h> + #include <asm/tdx.h> + #include <asm/vmx.h> +@@ -14,6 +15,8 @@ + #include <asm/insn.h> + #include <asm/insn-eval.h> + #include <asm/pgtable.h> ++#include <asm/set_memory.h> ++#include <asm/traps.h> + + /* MMIO direction */ + #define EPT_READ 0 +@@ -38,6 +41,8 @@ + + #define TDREPORT_SUBTYPE_0 0 + ++static atomic_long_t nr_shared; ++ + /* Called from __tdx_hypercall() for unrecoverable failure */ + noinstr void __noreturn __tdx_hypercall_failed(void) + { +@@ -429,6 +434,11 @@ static int handle_mmio(struct pt_regs *regs, struct ve_info *ve) + return -EINVAL; + } + ++ if (!fault_in_kernel_space(ve->gla)) { ++ WARN_ONCE(1, "Access to userspace address is not supported"); ++ return -EINVAL; ++ } ++ + /* + * Reject EPT violation #VEs that split pages. + * +@@ -797,28 +807,124 @@ static bool tdx_enc_status_changed(unsigned long vaddr, int numpages, bool enc) + return true; + } + +-static bool tdx_enc_status_change_prepare(unsigned long vaddr, int numpages, +- bool enc) ++static int tdx_enc_status_change_prepare(unsigned long vaddr, int numpages, ++ bool enc) + { + /* + * Only handle shared->private conversion here. + * See the comment in tdx_early_init(). + */ +- if (enc) +- return tdx_enc_status_changed(vaddr, numpages, enc); +- return true; ++ if (enc && !tdx_enc_status_changed(vaddr, numpages, enc)) ++ return -EIO; ++ ++ return 0; + } + +-static bool tdx_enc_status_change_finish(unsigned long vaddr, int numpages, ++static int tdx_enc_status_change_finish(unsigned long vaddr, int numpages, + bool enc) + { + /* + * Only handle private->shared conversion here. + * See the comment in tdx_early_init(). + */ +- if (!enc) +- return tdx_enc_status_changed(vaddr, numpages, enc); +- return true; ++ if (!enc && !tdx_enc_status_changed(vaddr, numpages, enc)) ++ return -EIO; ++ ++ if (enc) ++ atomic_long_sub(numpages, &nr_shared); ++ else ++ atomic_long_add(numpages, &nr_shared); ++ ++ return 0; ++} ++ ++/* Stop new private<->shared conversions */ ++static void tdx_kexec_begin(void) ++{ ++ if (!IS_ENABLED(CONFIG_KEXEC_CORE)) ++ return; ++ ++ /* ++ * Crash kernel reaches here with interrupts disabled: can't wait for ++ * conversions to finish. ++ * ++ * If race happened, just report and proceed. ++ */ ++ if (!set_memory_enc_stop_conversion()) ++ pr_warn("Failed to stop shared<->private conversions\n"); ++} ++ ++/* Walk direct mapping and convert all shared memory back to private */ ++static void tdx_kexec_finish(void) ++{ ++ unsigned long addr, end; ++ long found = 0, shared; ++ ++ if (!IS_ENABLED(CONFIG_KEXEC_CORE)) ++ return; ++ ++ lockdep_assert_irqs_disabled(); ++ ++ addr = PAGE_OFFSET; ++ end = PAGE_OFFSET + get_max_mapped(); ++ ++ while (addr < end) { ++ unsigned long size; ++ unsigned int level; ++ pte_t *pte; ++ ++ pte = lookup_address(addr, &level); ++ size = page_level_size(level); ++ ++ if (pte && pte_decrypted(*pte)) { ++ int pages = size / PAGE_SIZE; ++ ++ /* ++ * Touching memory with shared bit set triggers implicit ++ * conversion to shared. ++ * ++ * Make sure nobody touches the shared range from ++ * now on. ++ */ ++ set_pte(pte, __pte(0)); ++ ++ /* ++ * Memory encryption state persists across kexec. ++ * If tdx_enc_status_changed() fails in the first ++ * kernel, it leaves memory in an unknown state. ++ * ++ * If that memory remains shared, accessing it in the ++ * *next* kernel through a private mapping will result ++ * in an unrecoverable guest shutdown. ++ * ++ * The kdump kernel boot is not impacted as it uses ++ * a pre-reserved memory range that is always private. ++ * However, gathering crash information could lead to ++ * a crash if it accesses unconverted memory through ++ * a private mapping which is possible when accessing ++ * that memory through /proc/vmcore, for example. ++ * ++ * In all cases, print error info in order to leave ++ * enough bread crumbs for debugging. ++ */ ++ if (!tdx_enc_status_changed(addr, pages, true)) { ++ pr_err("Failed to unshare range %#lx-%#lx\n", ++ addr, addr + size); ++ } ++ ++ found += pages; ++ } ++ ++ addr += size; ++ } ++ ++ __flush_tlb_all(); ++ ++ shared = atomic_long_read(&nr_shared); ++ if (shared != found) { ++ pr_err("shared page accounting is off\n"); ++ pr_err("nr_shared = %ld, nr_found = %ld\n", shared, found); ++ } + } + + void __init tdx_early_init(void) +@@ -880,6 +986,9 @@ void __init tdx_early_init(void) + x86_platform.guest.enc_cache_flush_required = tdx_cache_flush_required; + x86_platform.guest.enc_tlb_flush_required = tdx_tlb_flush_required; + ++ x86_platform.guest.enc_kexec_begin = tdx_kexec_begin; ++ x86_platform.guest.enc_kexec_finish = tdx_kexec_finish; ++ + /* + * TDX intercepts the RDMSR to read the X2APIC ID in the parallel + * bringup low level code. That raises #VE which cannot be handled +diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c +index dcac96133cb6a9..28757629d0d830 100644 +--- a/arch/x86/events/intel/core.c ++++ b/arch/x86/events/intel/core.c +@@ -3912,8 +3912,12 @@ static int intel_pmu_hw_config(struct perf_event *event) + x86_pmu.pebs_aliases(event); + } + +- if (needs_branch_stack(event) && is_sampling_event(event)) +- event->hw.flags |= PERF_X86_EVENT_NEEDS_BRANCH_STACK; ++ if (needs_branch_stack(event)) { ++ /* Avoid branch stack setup for counting events in SAMPLE READ */ ++ if (is_sampling_event(event) || ++ !(event->attr.sample_type & PERF_SAMPLE_READ)) ++ event->hw.flags |= PERF_X86_EVENT_NEEDS_BRANCH_STACK; ++ } + + if (branch_sample_counters(event)) { + struct perf_event *leader, *sibling; +diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c +index b4aa8daa47738f..2959970dd10eb1 100644 +--- a/arch/x86/events/intel/pt.c ++++ b/arch/x86/events/intel/pt.c +@@ -1606,6 +1606,7 @@ static void pt_event_stop(struct perf_event *event, int mode) + * see comment in intel_pt_interrupt(). + */ + WRITE_ONCE(pt->handle_nmi, 0); ++ barrier(); + + pt_config_stop(event); + +@@ -1657,11 +1658,10 @@ static long pt_event_snapshot_aux(struct perf_event *event, + return 0; + + /* +- * Here, handle_nmi tells us if the tracing is on ++ * There is no PT interrupt in this mode, so stop the trace and it will ++ * remain stopped while the buffer is copied. + */ +- if (READ_ONCE(pt->handle_nmi)) +- pt_config_stop(event); +- ++ pt_config_stop(event); + pt_read_offset(buf); + pt_update_head(pt); + +@@ -1673,11 +1673,10 @@ static long pt_event_snapshot_aux(struct perf_event *event, + ret = perf_output_copy_aux(&pt->handle, handle, from, to); + + /* +- * If the tracing was on when we turned up, restart it. +- * Compiler barrier not needed as we couldn't have been +- * preempted by anything that touches pt->handle_nmi. ++ * Here, handle_nmi tells us if the tracing was on. ++ * If the tracing was on, restart it. + */ +- if (pt->handle_nmi) ++ if (READ_ONCE(pt->handle_nmi)) + pt_config_start(event); + + return ret; +diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c +index 768d73de0d098a..b4a851d27c7cb8 100644 +--- a/arch/x86/hyperv/ivm.c ++++ b/arch/x86/hyperv/ivm.c +@@ -523,9 +523,9 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[], + * transition is complete, hv_vtom_set_host_visibility() marks the pages + * as "present" again. + */ +-static bool hv_vtom_clear_present(unsigned long kbuffer, int pagecount, bool enc) ++static int hv_vtom_clear_present(unsigned long kbuffer, int pagecount, bool enc) + { +- return !set_memory_np(kbuffer, pagecount); ++ return set_memory_np(kbuffer, pagecount); + } + + /* +@@ -536,20 +536,19 @@ static bool hv_vtom_clear_present(unsigned long kbuffer, int pagecount, bool enc + * with host. This function works as wrap of hv_mark_gpa_visibility() + * with memory base and size. + */ +-static bool hv_vtom_set_host_visibility(unsigned long kbuffer, int pagecount, bool enc) ++static int hv_vtom_set_host_visibility(unsigned long kbuffer, int pagecount, bool enc) + { + enum hv_mem_host_visibility visibility = enc ? + VMBUS_PAGE_NOT_VISIBLE : VMBUS_PAGE_VISIBLE_READ_WRITE; + u64 *pfn_array; + phys_addr_t paddr; ++ int i, pfn, err; + void *vaddr; + int ret = 0; +- bool result = true; +- int i, pfn; + + pfn_array = kmalloc(HV_HYP_PAGE_SIZE, GFP_KERNEL); + if (!pfn_array) { +- result = false; ++ ret = -ENOMEM; + goto err_set_memory_p; + } + +@@ -568,10 +567,8 @@ static bool hv_vtom_set_host_visibility(unsigned long kbuffer, int pagecount, bo + if (pfn == HV_MAX_MODIFY_GPA_REP_COUNT || i == pagecount - 1) { + ret = hv_mark_gpa_visibility(pfn, pfn_array, + visibility); +- if (ret) { +- result = false; ++ if (ret) + goto err_free_pfn_array; +- } + pfn = 0; + } + } +@@ -586,10 +583,11 @@ static bool hv_vtom_set_host_visibility(unsigned long kbuffer, int pagecount, bo + * order to avoid leaving the memory range in a "broken" state. Setting + * the PRESENT bits shouldn't fail, but return an error if it does. + */ +- if (set_memory_p(kbuffer, pagecount)) +- result = false; ++ err = set_memory_p(kbuffer, pagecount); ++ if (err && !ret) ++ ret = err; + +- return result; ++ return ret; + } + + static bool hv_vtom_tlb_flush_required(bool private) +diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h +index 5af926c050f094..041efa274eebd6 100644 +--- a/arch/x86/include/asm/acpi.h ++++ b/arch/x86/include/asm/acpi.h +@@ -167,6 +167,14 @@ void acpi_generic_reduced_hw_init(void); + void x86_default_set_root_pointer(u64 addr); + u64 x86_default_get_root_pointer(void); + ++#ifdef CONFIG_XEN_PV ++/* A Xen PV domain needs a special acpi_os_ioremap() handling. */ ++extern void __iomem * (*acpi_os_ioremap)(acpi_physical_address phys, ++ acpi_size size); ++void __iomem *x86_acpi_os_ioremap(acpi_physical_address phys, acpi_size size); ++#define acpi_os_ioremap acpi_os_ioremap ++#endif ++ + #else /* !CONFIG_ACPI */ + + #define acpi_lapic 0 +diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h +index c67fa6ad098aae..6ffa8b75f4cd33 100644 +--- a/arch/x86/include/asm/hardirq.h ++++ b/arch/x86/include/asm/hardirq.h +@@ -69,7 +69,11 @@ extern u64 arch_irq_stat(void); + #define local_softirq_pending_ref pcpu_hot.softirq_pending + + #if IS_ENABLED(CONFIG_KVM_INTEL) +-static inline void kvm_set_cpu_l1tf_flush_l1d(void) ++/* ++ * This function is called from noinstr interrupt contexts ++ * and must be inlined to not get instrumentation. ++ */ ++static __always_inline void kvm_set_cpu_l1tf_flush_l1d(void) + { + __this_cpu_write(irq_stat.kvm_cpu_l1tf_flush_l1d, 1); + } +@@ -84,7 +88,7 @@ static __always_inline bool kvm_get_cpu_l1tf_flush_l1d(void) + return __this_cpu_read(irq_stat.kvm_cpu_l1tf_flush_l1d); + } + #else /* !IS_ENABLED(CONFIG_KVM_INTEL) */ +-static inline void kvm_set_cpu_l1tf_flush_l1d(void) { } ++static __always_inline void kvm_set_cpu_l1tf_flush_l1d(void) { } + #endif /* IS_ENABLED(CONFIG_KVM_INTEL) */ + + #endif /* _ASM_X86_HARDIRQ_H */ +diff --git a/arch/x86/include/asm/idtentry.h b/arch/x86/include/asm/idtentry.h +index d4f24499b256c8..ad5c68f0509d4d 100644 +--- a/arch/x86/include/asm/idtentry.h ++++ b/arch/x86/include/asm/idtentry.h +@@ -212,8 +212,8 @@ __visible noinstr void func(struct pt_regs *regs, \ + irqentry_state_t state = irqentry_enter(regs); \ + u32 vector = (u32)(u8)error_code; \ + \ ++ kvm_set_cpu_l1tf_flush_l1d(); \ + instrumentation_begin(); \ +- kvm_set_cpu_l1tf_flush_l1d(); \ + run_irq_on_irqstack_cond(__##func, regs, vector); \ + instrumentation_end(); \ + irqentry_exit(regs, state); \ +@@ -250,7 +250,6 @@ static void __##func(struct pt_regs *regs); \ + \ + static __always_inline void instr_##func(struct pt_regs *regs) \ + { \ +- kvm_set_cpu_l1tf_flush_l1d(); \ + run_sysvec_on_irqstack_cond(__##func, regs); \ + } \ + \ +@@ -258,6 +257,7 @@ __visible noinstr void func(struct pt_regs *regs) \ + { \ + irqentry_state_t state = irqentry_enter(regs); \ + \ ++ kvm_set_cpu_l1tf_flush_l1d(); \ + instrumentation_begin(); \ + instr_##func (regs); \ + instrumentation_end(); \ +@@ -288,7 +288,6 @@ static __always_inline void __##func(struct pt_regs *regs); \ + static __always_inline void instr_##func(struct pt_regs *regs) \ + { \ + __irq_enter_raw(); \ +- kvm_set_cpu_l1tf_flush_l1d(); \ + __##func (regs); \ + __irq_exit_raw(); \ + } \ +@@ -297,6 +296,7 @@ __visible noinstr void func(struct pt_regs *regs) \ + { \ + irqentry_state_t state = irqentry_enter(regs); \ + \ ++ kvm_set_cpu_l1tf_flush_l1d(); \ + instrumentation_begin(); \ + instr_##func (regs); \ + instrumentation_end(); \ +diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h +index d0274b3be2c400..e18399d08fb178 100644 +--- a/arch/x86/include/asm/kvm_host.h ++++ b/arch/x86/include/asm/kvm_host.h +@@ -1708,7 +1708,8 @@ struct kvm_x86_ops { + void (*enable_nmi_window)(struct kvm_vcpu *vcpu); + void (*enable_irq_window)(struct kvm_vcpu *vcpu); + void (*update_cr8_intercept)(struct kvm_vcpu *vcpu, int tpr, int irr); +- bool (*check_apicv_inhibit_reasons)(enum kvm_apicv_inhibit reason); ++ ++ const bool x2apic_icr_is_split; + const unsigned long required_apicv_inhibits; + bool allow_apicv_in_x2apic_without_x2apic_virtualization; + void (*refresh_apicv_exec_ctrl)(struct kvm_vcpu *vcpu); +diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h +index 65b8e5bb902cc3..e39311a89bf478 100644 +--- a/arch/x86/include/asm/pgtable.h ++++ b/arch/x86/include/asm/pgtable.h +@@ -140,6 +140,11 @@ static inline int pte_young(pte_t pte) + return pte_flags(pte) & _PAGE_ACCESSED; + } + ++static inline bool pte_decrypted(pte_t pte) ++{ ++ return cc_mkdec(pte_val(pte)) == pte_val(pte); ++} ++ + #define pmd_dirty pmd_dirty + static inline bool pmd_dirty(pmd_t pmd) + { +diff --git a/arch/x86/include/asm/set_memory.h b/arch/x86/include/asm/set_memory.h +index 9aee31862b4a8b..4b2abce2e3e7d6 100644 +--- a/arch/x86/include/asm/set_memory.h ++++ b/arch/x86/include/asm/set_memory.h +@@ -49,8 +49,11 @@ int set_memory_wb(unsigned long addr, int numpages); + int set_memory_np(unsigned long addr, int numpages); + int set_memory_p(unsigned long addr, int numpages); + int set_memory_4k(unsigned long addr, int numpages); ++ ++bool set_memory_enc_stop_conversion(void); + int set_memory_encrypted(unsigned long addr, int numpages); + int set_memory_decrypted(unsigned long addr, int numpages); ++ + int set_memory_np_noalias(unsigned long addr, int numpages); + int set_memory_nonglobal(unsigned long addr, int numpages); + int set_memory_global(unsigned long addr, int numpages); +diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h +index 6149eabe200f5b..213cf5379a5a6d 100644 +--- a/arch/x86/include/asm/x86_init.h ++++ b/arch/x86/include/asm/x86_init.h +@@ -149,12 +149,22 @@ struct x86_init_acpi { + * @enc_status_change_finish Notify HV after the encryption status of a range is changed + * @enc_tlb_flush_required Returns true if a TLB flush is needed before changing page encryption status + * @enc_cache_flush_required Returns true if a cache flush is needed before changing page encryption status ++ * @enc_kexec_begin Begin the two-step process of converting shared memory back ++ * to private. It stops the new conversions from being started ++ * and waits in-flight conversions to finish, if possible. ++ * @enc_kexec_finish Finish the two-step process of converting shared memory to ++ * private. All memory is private after the call when ++ * the function returns. ++ * It is called on only one CPU while the others are shut down ++ * and with interrupts disabled. + */ + struct x86_guest { +- bool (*enc_status_change_prepare)(unsigned long vaddr, int npages, bool enc); +- bool (*enc_status_change_finish)(unsigned long vaddr, int npages, bool enc); ++ int (*enc_status_change_prepare)(unsigned long vaddr, int npages, bool enc); ++ int (*enc_status_change_finish)(unsigned long vaddr, int npages, bool enc); + bool (*enc_tlb_flush_required)(bool enc); + bool (*enc_cache_flush_required)(void); ++ void (*enc_kexec_begin)(void); ++ void (*enc_kexec_finish)(void); + }; + + /** +diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c +index 4bf82dbd2a6b5a..01e929a0f6ccc1 100644 +--- a/arch/x86/kernel/acpi/boot.c ++++ b/arch/x86/kernel/acpi/boot.c +@@ -1862,3 +1862,14 @@ u64 x86_default_get_root_pointer(void) + { + return boot_params.acpi_rsdp_addr; + } ++ ++#ifdef CONFIG_XEN_PV ++void __iomem *x86_acpi_os_ioremap(acpi_physical_address phys, acpi_size size) ++{ ++ return ioremap_cache(phys, size); ++} ++ ++void __iomem * (*acpi_os_ioremap)(acpi_physical_address phys, acpi_size size) = ++ x86_acpi_os_ioremap; ++EXPORT_SYMBOL_GPL(acpi_os_ioremap); ++#endif +diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c +index 27892e57c4ef93..6aeeb43dd3f6a8 100644 +--- a/arch/x86/kernel/cpu/sgx/main.c ++++ b/arch/x86/kernel/cpu/sgx/main.c +@@ -475,24 +475,25 @@ struct sgx_epc_page *__sgx_alloc_epc_page(void) + { + struct sgx_epc_page *page; + int nid_of_current = numa_node_id(); +- int nid = nid_of_current; ++ int nid_start, nid; + +- if (node_isset(nid_of_current, sgx_numa_mask)) { +- page = __sgx_alloc_epc_page_from_node(nid_of_current); +- if (page) +- return page; +- } +- +- /* Fall back to the non-local NUMA nodes: */ +- while (true) { +- nid = next_node_in(nid, sgx_numa_mask); +- if (nid == nid_of_current) +- break; ++ /* ++ * Try local node first. If it doesn't have an EPC section, ++ * fall back to the non-local NUMA nodes. ++ */ ++ if (node_isset(nid_of_current, sgx_numa_mask)) ++ nid_start = nid_of_current; ++ else ++ nid_start = next_node_in(nid_of_current, sgx_numa_mask); + ++ nid = nid_start; ++ do { + page = __sgx_alloc_epc_page_from_node(nid); + if (page) + return page; +- } ++ ++ nid = next_node_in(nid, sgx_numa_mask); ++ } while (nid != nid_start); + + return ERR_PTR(-ENOMEM); + } +diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c +index f06501445cd981..340af815565848 100644 +--- a/arch/x86/kernel/crash.c ++++ b/arch/x86/kernel/crash.c +@@ -128,6 +128,18 @@ void native_machine_crash_shutdown(struct pt_regs *regs) + #ifdef CONFIG_HPET_TIMER + hpet_disable(); + #endif ++ ++ /* ++ * Non-crash kexec calls enc_kexec_begin() while scheduling is still ++ * active. This allows the callback to wait until all in-flight ++ * shared<->private conversions are complete. In a crash scenario, ++ * enc_kexec_begin() gets called after all but one CPU have been shut ++ * down and interrupts have been disabled. This allows the callback to ++ * detect a race with the conversion and report it. ++ */ ++ x86_platform.guest.enc_kexec_begin(); ++ x86_platform.guest.enc_kexec_finish(); ++ + crash_save_cpu(regs, safe_smp_processor_id()); + } + +diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c +index a817ed0724d1e7..4b9d4557fc94a4 100644 +--- a/arch/x86/kernel/head64.c ++++ b/arch/x86/kernel/head64.c +@@ -559,10 +559,11 @@ void early_setup_idt(void) + */ + void __head startup_64_setup_gdt_idt(void) + { ++ struct desc_struct *gdt = (void *)(__force unsigned long)init_per_cpu_var(gdt_page.gdt); + void *handler = NULL; + + struct desc_ptr startup_gdt_descr = { +- .address = (unsigned long)&RIP_REL_REF(init_per_cpu_var(gdt_page.gdt)), ++ .address = (unsigned long)&RIP_REL_REF(*gdt), + .size = GDT_SIZE - 1, + }; + +diff --git a/arch/x86/kernel/jailhouse.c b/arch/x86/kernel/jailhouse.c +index df337860612d84..cd8ed1edbf9ee7 100644 +--- a/arch/x86/kernel/jailhouse.c ++++ b/arch/x86/kernel/jailhouse.c +@@ -12,6 +12,7 @@ + #include <linux/kernel.h> + #include <linux/reboot.h> + #include <linux/serial_8250.h> ++#include <linux/acpi.h> + #include <asm/apic.h> + #include <asm/io_apic.h> + #include <asm/acpi.h> +diff --git a/arch/x86/kernel/mmconf-fam10h_64.c b/arch/x86/kernel/mmconf-fam10h_64.c +index c94dec6a18345a..1f54eedc3015e9 100644 +--- a/arch/x86/kernel/mmconf-fam10h_64.c ++++ b/arch/x86/kernel/mmconf-fam10h_64.c +@@ -9,6 +9,7 @@ + #include <linux/pci.h> + #include <linux/dmi.h> + #include <linux/range.h> ++#include <linux/acpi.h> + + #include <asm/pci-direct.h> + #include <linux/sort.h> +diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c +index 6d3d20e3e43a9b..d8d582b750d4f6 100644 +--- a/arch/x86/kernel/process_64.c ++++ b/arch/x86/kernel/process_64.c +@@ -798,6 +798,27 @@ static long prctl_map_vdso(const struct vdso_image *image, unsigned long addr) + + #define LAM_U57_BITS 6 + ++static void enable_lam_func(void *__mm) ++{ ++ struct mm_struct *mm = __mm; ++ ++ if (this_cpu_read(cpu_tlbstate.loaded_mm) == mm) { ++ write_cr3(__read_cr3() | mm->context.lam_cr3_mask); ++ set_tlbstate_lam_mode(mm); ++ } ++} ++ ++static void mm_enable_lam(struct mm_struct *mm) ++{ ++ /* ++ * Even though the process must still be single-threaded at this ++ * point, kernel threads may be using the mm. IPI those kernel ++ * threads if they exist. ++ */ ++ on_each_cpu_mask(mm_cpumask(mm), enable_lam_func, mm, true); ++ set_bit(MM_CONTEXT_LOCK_LAM, &mm->context.flags); ++} ++ + static int prctl_enable_tagged_addr(struct mm_struct *mm, unsigned long nr_bits) + { + if (!cpu_feature_enabled(X86_FEATURE_LAM)) +@@ -814,6 +835,10 @@ static int prctl_enable_tagged_addr(struct mm_struct *mm, unsigned long nr_bits) + if (mmap_write_lock_killable(mm)) + return -EINTR; + ++ /* ++ * MM_CONTEXT_LOCK_LAM is set on clone. Prevent LAM from ++ * being enabled unless the process is single threaded: ++ */ + if (test_bit(MM_CONTEXT_LOCK_LAM, &mm->context.flags)) { + mmap_write_unlock(mm); + return -EBUSY; +@@ -830,9 +855,7 @@ static int prctl_enable_tagged_addr(struct mm_struct *mm, unsigned long nr_bits) + return -EINVAL; + } + +- write_cr3(__read_cr3() | mm->context.lam_cr3_mask); +- set_tlbstate_lam_mode(mm); +- set_bit(MM_CONTEXT_LOCK_LAM, &mm->context.flags); ++ mm_enable_lam(mm); + + mmap_write_unlock(mm); + +diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c +index f3130f762784a1..bb7a44af7efd19 100644 +--- a/arch/x86/kernel/reboot.c ++++ b/arch/x86/kernel/reboot.c +@@ -12,6 +12,7 @@ + #include <linux/delay.h> + #include <linux/objtool.h> + #include <linux/pgtable.h> ++#include <linux/kexec.h> + #include <acpi/reboot.h> + #include <asm/io.h> + #include <asm/apic.h> +@@ -716,6 +717,14 @@ static void native_machine_emergency_restart(void) + + void native_machine_shutdown(void) + { ++ /* ++ * Call enc_kexec_begin() while all CPUs are still active and ++ * interrupts are enabled. This will allow all in-flight memory ++ * conversions to finish cleanly. ++ */ ++ if (kexec_in_progress) ++ x86_platform.guest.enc_kexec_begin(); ++ + /* Stop the cpus and apics */ + #ifdef CONFIG_X86_IO_APIC + /* +@@ -752,6 +761,9 @@ void native_machine_shutdown(void) + #ifdef CONFIG_X86_64 + x86_platform.iommu_shutdown(); + #endif ++ ++ if (kexec_in_progress) ++ x86_platform.guest.enc_kexec_finish(); + } + + static void __machine_emergency_restart(int emergency) +diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c +index 0c35207320cb4f..390e4fe7433ea3 100644 +--- a/arch/x86/kernel/smpboot.c ++++ b/arch/x86/kernel/smpboot.c +@@ -60,6 +60,7 @@ + #include <linux/stackprotector.h> + #include <linux/cpuhotplug.h> + #include <linux/mc146818rtc.h> ++#include <linux/acpi.h> + + #include <asm/acpi.h> + #include <asm/cacheinfo.h> +diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c +index d5dc5a92635a82..0a2bbd674a6d99 100644 +--- a/arch/x86/kernel/x86_init.c ++++ b/arch/x86/kernel/x86_init.c +@@ -8,6 +8,7 @@ + #include <linux/ioport.h> + #include <linux/export.h> + #include <linux/pci.h> ++#include <linux/acpi.h> + + #include <asm/acpi.h> + #include <asm/bios_ebda.h> +@@ -134,10 +135,12 @@ struct x86_cpuinit_ops x86_cpuinit = { + + static void default_nmi_init(void) { }; + +-static bool enc_status_change_prepare_noop(unsigned long vaddr, int npages, bool enc) { return true; } +-static bool enc_status_change_finish_noop(unsigned long vaddr, int npages, bool enc) { return true; } ++static int enc_status_change_prepare_noop(unsigned long vaddr, int npages, bool enc) { return 0; } ++static int enc_status_change_finish_noop(unsigned long vaddr, int npages, bool enc) { return 0; } + static bool enc_tlb_flush_required_noop(bool enc) { return false; } + static bool enc_cache_flush_required_noop(void) { return false; } ++static void enc_kexec_begin_noop(void) {} ++static void enc_kexec_finish_noop(void) {} + static bool is_private_mmio_noop(u64 addr) {return false; } + + struct x86_platform_ops x86_platform __ro_after_init = { +@@ -161,6 +164,8 @@ struct x86_platform_ops x86_platform __ro_after_init = { + .enc_status_change_finish = enc_status_change_finish_noop, + .enc_tlb_flush_required = enc_tlb_flush_required_noop, + .enc_cache_flush_required = enc_cache_flush_required_noop, ++ .enc_kexec_begin = enc_kexec_begin_noop, ++ .enc_kexec_finish = enc_kexec_finish_noop, + }, + }; + +diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c +index acd7d48100a1d3..523d02c50562f4 100644 +--- a/arch/x86/kvm/lapic.c ++++ b/arch/x86/kvm/lapic.c +@@ -351,10 +351,8 @@ static void kvm_recalculate_logical_map(struct kvm_apic_map *new, + * reversing the LDR calculation to get cluster of APICs, i.e. no + * additional work is required. + */ +- if (apic_x2apic_mode(apic)) { +- WARN_ON_ONCE(ldr != kvm_apic_calc_x2apic_ldr(kvm_x2apic_id(apic))); ++ if (apic_x2apic_mode(apic)) + return; +- } + + if (WARN_ON_ONCE(!kvm_apic_map_get_logical_dest(new, ldr, + &cluster, &mask))) { +@@ -2453,6 +2451,43 @@ void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu) + } + EXPORT_SYMBOL_GPL(kvm_lapic_set_eoi); + ++#define X2APIC_ICR_RESERVED_BITS (GENMASK_ULL(31, 20) | GENMASK_ULL(17, 16) | BIT(13)) ++ ++int kvm_x2apic_icr_write(struct kvm_lapic *apic, u64 data) ++{ ++ if (data & X2APIC_ICR_RESERVED_BITS) ++ return 1; ++ ++ /* ++ * The BUSY bit is reserved on both Intel and AMD in x2APIC mode, but ++ * only AMD requires it to be zero, Intel essentially just ignores the ++ * bit. And if IPI virtualization (Intel) or x2AVIC (AMD) is enabled, ++ * the CPU performs the reserved bits checks, i.e. the underlying CPU ++ * behavior will "win". Arbitrarily clear the BUSY bit, as there is no ++ * sane way to provide consistent behavior with respect to hardware. ++ */ ++ data &= ~APIC_ICR_BUSY; ++ ++ kvm_apic_send_ipi(apic, (u32)data, (u32)(data >> 32)); ++ if (kvm_x86_ops.x2apic_icr_is_split) { ++ kvm_lapic_set_reg(apic, APIC_ICR, data); ++ kvm_lapic_set_reg(apic, APIC_ICR2, data >> 32); ++ } else { ++ kvm_lapic_set_reg64(apic, APIC_ICR, data); ++ } ++ trace_kvm_apic_write(APIC_ICR, data); ++ return 0; ++} ++ ++static u64 kvm_x2apic_icr_read(struct kvm_lapic *apic) ++{ ++ if (kvm_x86_ops.x2apic_icr_is_split) ++ return (u64)kvm_lapic_get_reg(apic, APIC_ICR) | ++ (u64)kvm_lapic_get_reg(apic, APIC_ICR2) << 32; ++ ++ return kvm_lapic_get_reg64(apic, APIC_ICR); ++} ++ + /* emulate APIC access in a trap manner */ + void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset) + { +@@ -2470,7 +2505,7 @@ void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset) + * maybe-unecessary write, and both are in the noise anyways. + */ + if (apic_x2apic_mode(apic) && offset == APIC_ICR) +- kvm_x2apic_icr_write(apic, kvm_lapic_get_reg64(apic, APIC_ICR)); ++ WARN_ON_ONCE(kvm_x2apic_icr_write(apic, kvm_x2apic_icr_read(apic))); + else + kvm_lapic_reg_write(apic, offset, kvm_lapic_get_reg(apic, offset)); + } +@@ -2964,34 +2999,48 @@ static int kvm_apic_state_fixup(struct kvm_vcpu *vcpu, + struct kvm_lapic_state *s, bool set) + { + if (apic_x2apic_mode(vcpu->arch.apic)) { ++ u32 x2apic_id = kvm_x2apic_id(vcpu->arch.apic); + u32 *id = (u32 *)(s->regs + APIC_ID); + u32 *ldr = (u32 *)(s->regs + APIC_LDR); + u64 icr; + + if (vcpu->kvm->arch.x2apic_format) { +- if (*id != vcpu->vcpu_id) ++ if (*id != x2apic_id) + return -EINVAL; + } else { ++ /* ++ * Ignore the userspace value when setting APIC state. ++ * KVM's model is that the x2APIC ID is readonly, e.g. ++ * KVM only supports delivering interrupts to KVM's ++ * version of the x2APIC ID. However, for backwards ++ * compatibility, don't reject attempts to set a ++ * mismatched ID for userspace that hasn't opted into ++ * x2apic_format. ++ */ + if (set) +- *id >>= 24; ++ *id = x2apic_id; + else +- *id <<= 24; ++ *id = x2apic_id << 24; + } + + /* + * In x2APIC mode, the LDR is fixed and based on the id. And +- * ICR is internally a single 64-bit register, but needs to be +- * split to ICR+ICR2 in userspace for backwards compatibility. ++ * if the ICR is _not_ split, ICR is internally a single 64-bit ++ * register, but needs to be split to ICR+ICR2 in userspace for ++ * backwards compatibility. + */ +- if (set) { +- *ldr = kvm_apic_calc_x2apic_ldr(*id); +- +- icr = __kvm_lapic_get_reg(s->regs, APIC_ICR) | +- (u64)__kvm_lapic_get_reg(s->regs, APIC_ICR2) << 32; +- __kvm_lapic_set_reg64(s->regs, APIC_ICR, icr); +- } else { +- icr = __kvm_lapic_get_reg64(s->regs, APIC_ICR); +- __kvm_lapic_set_reg(s->regs, APIC_ICR2, icr >> 32); ++ if (set) ++ *ldr = kvm_apic_calc_x2apic_ldr(x2apic_id); ++ ++ if (!kvm_x86_ops.x2apic_icr_is_split) { ++ if (set) { ++ icr = __kvm_lapic_get_reg(s->regs, APIC_ICR) | ++ (u64)__kvm_lapic_get_reg(s->regs, APIC_ICR2) << 32; ++ __kvm_lapic_set_reg64(s->regs, APIC_ICR, icr); ++ } else { ++ icr = __kvm_lapic_get_reg64(s->regs, APIC_ICR); ++ __kvm_lapic_set_reg(s->regs, APIC_ICR2, icr >> 32); ++ } + } + } + +@@ -3183,22 +3232,12 @@ int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr) + return 0; + } + +-int kvm_x2apic_icr_write(struct kvm_lapic *apic, u64 data) +-{ +- data &= ~APIC_ICR_BUSY; +- +- kvm_apic_send_ipi(apic, (u32)data, (u32)(data >> 32)); +- kvm_lapic_set_reg64(apic, APIC_ICR, data); +- trace_kvm_apic_write(APIC_ICR, data); +- return 0; +-} +- + static int kvm_lapic_msr_read(struct kvm_lapic *apic, u32 reg, u64 *data) + { + u32 low; + + if (reg == APIC_ICR) { +- *data = kvm_lapic_get_reg64(apic, APIC_ICR); ++ *data = kvm_x2apic_icr_read(apic); + return 0; + } + +diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c +index 0357f7af559665..6d5da700268a5b 100644 +--- a/arch/x86/kvm/svm/svm.c ++++ b/arch/x86/kvm/svm/svm.c +@@ -5051,6 +5051,8 @@ static struct kvm_x86_ops svm_x86_ops __initdata = { + .enable_nmi_window = svm_enable_nmi_window, + .enable_irq_window = svm_enable_irq_window, + .update_cr8_intercept = svm_update_cr8_intercept, ++ ++ .x2apic_icr_is_split = true, + .set_virtual_apic_mode = avic_refresh_virtual_apic_mode, + .refresh_apicv_exec_ctrl = avic_refresh_apicv_exec_ctrl, + .apicv_post_state_restore = avic_apicv_post_state_restore, +diff --git a/arch/x86/kvm/vmx/main.c b/arch/x86/kvm/vmx/main.c +index 547fca3709febd..35c2c004dacd2b 100644 +--- a/arch/x86/kvm/vmx/main.c ++++ b/arch/x86/kvm/vmx/main.c +@@ -89,6 +89,8 @@ struct kvm_x86_ops vt_x86_ops __initdata = { + .enable_nmi_window = vmx_enable_nmi_window, + .enable_irq_window = vmx_enable_irq_window, + .update_cr8_intercept = vmx_update_cr8_intercept, ++ ++ .x2apic_icr_is_split = false, + .set_virtual_apic_mode = vmx_set_virtual_apic_mode, + .set_apic_access_page_addr = vmx_set_apic_access_page_addr, + .refresh_apicv_exec_ctrl = vmx_refresh_apicv_exec_ctrl, +diff --git a/arch/x86/kvm/vmx/x86_ops.h b/arch/x86/kvm/vmx/x86_ops.h +index d404227c164d60..e46aba18600e7a 100644 +--- a/arch/x86/kvm/vmx/x86_ops.h ++++ b/arch/x86/kvm/vmx/x86_ops.h +@@ -46,7 +46,6 @@ bool vmx_apic_init_signal_blocked(struct kvm_vcpu *vcpu); + void vmx_migrate_timers(struct kvm_vcpu *vcpu); + void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu); + void vmx_apicv_pre_state_restore(struct kvm_vcpu *vcpu); +-bool vmx_check_apicv_inhibit_reasons(enum kvm_apicv_inhibit reason); + void vmx_hwapic_irr_update(struct kvm_vcpu *vcpu, int max_irr); + void vmx_hwapic_isr_update(int max_isr); + int vmx_sync_pir_to_irr(struct kvm_vcpu *vcpu); +diff --git a/arch/x86/mm/mem_encrypt_amd.c b/arch/x86/mm/mem_encrypt_amd.c +index 422602f6039b82..e7b67519ddb5d3 100644 +--- a/arch/x86/mm/mem_encrypt_amd.c ++++ b/arch/x86/mm/mem_encrypt_amd.c +@@ -283,7 +283,7 @@ static void enc_dec_hypercall(unsigned long vaddr, unsigned long size, bool enc) + #endif + } + +-static bool amd_enc_status_change_prepare(unsigned long vaddr, int npages, bool enc) ++static int amd_enc_status_change_prepare(unsigned long vaddr, int npages, bool enc) + { + /* + * To maintain the security guarantees of SEV-SNP guests, make sure +@@ -292,11 +292,11 @@ static bool amd_enc_status_change_prepare(unsigned long vaddr, int npages, bool + if (cc_platform_has(CC_ATTR_GUEST_SEV_SNP) && !enc) + snp_set_memory_shared(vaddr, npages); + +- return true; ++ return 0; + } + + /* Return true unconditionally: return value doesn't matter for the SEV side */ +-static bool amd_enc_status_change_finish(unsigned long vaddr, int npages, bool enc) ++static int amd_enc_status_change_finish(unsigned long vaddr, int npages, bool enc) + { + /* + * After memory is mapped encrypted in the page table, validate it +@@ -308,7 +308,7 @@ static bool amd_enc_status_change_finish(unsigned long vaddr, int npages, bool e + if (!cc_platform_has(CC_ATTR_HOST_MEM_ENCRYPT)) + enc_dec_hypercall(vaddr, npages << PAGE_SHIFT, enc); + +- return true; ++ return 0; + } + + static void __init __set_clr_pte_enc(pte_t *kpte, int level, bool enc) +diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c +index 19fdfbb171ed6e..1356e25e6d1254 100644 +--- a/arch/x86/mm/pat/set_memory.c ++++ b/arch/x86/mm/pat/set_memory.c +@@ -2196,7 +2196,8 @@ static int __set_memory_enc_pgtable(unsigned long addr, int numpages, bool enc) + cpa_flush(&cpa, x86_platform.guest.enc_cache_flush_required()); + + /* Notify hypervisor that we are about to set/clr encryption attribute. */ +- if (!x86_platform.guest.enc_status_change_prepare(addr, numpages, enc)) ++ ret = x86_platform.guest.enc_status_change_prepare(addr, numpages, enc); ++ if (ret) + goto vmm_fail; + + ret = __change_page_attr_set_clr(&cpa, 1); +@@ -2214,24 +2215,61 @@ static int __set_memory_enc_pgtable(unsigned long addr, int numpages, bool enc) + return ret; + + /* Notify hypervisor that we have successfully set/clr encryption attribute. */ +- if (!x86_platform.guest.enc_status_change_finish(addr, numpages, enc)) ++ ret = x86_platform.guest.enc_status_change_finish(addr, numpages, enc); ++ if (ret) + goto vmm_fail; + + return 0; + + vmm_fail: +- WARN_ONCE(1, "CPA VMM failure to convert memory (addr=%p, numpages=%d) to %s.\n", +- (void *)addr, numpages, enc ? "private" : "shared"); ++ WARN_ONCE(1, "CPA VMM failure to convert memory (addr=%p, numpages=%d) to %s: %d\n", ++ (void *)addr, numpages, enc ? "private" : "shared", ret); + +- return -EIO; ++ return ret; ++} ++ ++/* ++ * The lock serializes conversions between private and shared memory. ++ * ++ * It is taken for read on conversion. A write lock guarantees that no ++ * concurrent conversions are in progress. ++ */ ++static DECLARE_RWSEM(mem_enc_lock); ++ ++/* ++ * Stop new private<->shared conversions. ++ * ++ * Taking the exclusive mem_enc_lock waits for in-flight conversions to complete. ++ * The lock is not released to prevent new conversions from being started. ++ */ ++bool set_memory_enc_stop_conversion(void) ++{ ++ /* ++ * In a crash scenario, sleep is not allowed. Try to take the lock. ++ * Failure indicates that there is a race with the conversion. ++ */ ++ if (oops_in_progress) ++ return down_write_trylock(&mem_enc_lock); ++ ++ down_write(&mem_enc_lock); ++ ++ return true; + } + + static int __set_memory_enc_dec(unsigned long addr, int numpages, bool enc) + { +- if (cc_platform_has(CC_ATTR_MEM_ENCRYPT)) +- return __set_memory_enc_pgtable(addr, numpages, enc); ++ int ret = 0; + +- return 0; ++ if (cc_platform_has(CC_ATTR_MEM_ENCRYPT)) { ++ if (!down_read_trylock(&mem_enc_lock)) ++ return -EBUSY; ++ ++ ret = __set_memory_enc_pgtable(addr, numpages, enc); ++ ++ up_read(&mem_enc_lock); ++ } ++ ++ return ret; + } + + int set_memory_encrypted(unsigned long addr, int numpages) +diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c +index 44ac64f3a047ca..a041d2ecd83804 100644 +--- a/arch/x86/mm/tlb.c ++++ b/arch/x86/mm/tlb.c +@@ -503,9 +503,9 @@ void switch_mm_irqs_off(struct mm_struct *unused, struct mm_struct *next, + { + struct mm_struct *prev = this_cpu_read(cpu_tlbstate.loaded_mm); + u16 prev_asid = this_cpu_read(cpu_tlbstate.loaded_mm_asid); +- unsigned long new_lam = mm_lam_cr3_mask(next); + bool was_lazy = this_cpu_read(cpu_tlbstate_shared.is_lazy); + unsigned cpu = smp_processor_id(); ++ unsigned long new_lam; + u64 next_tlb_gen; + bool need_flush; + u16 new_asid; +@@ -619,9 +619,7 @@ void switch_mm_irqs_off(struct mm_struct *unused, struct mm_struct *next, + cpumask_clear_cpu(cpu, mm_cpumask(prev)); + } + +- /* +- * Start remote flushes and then read tlb_gen. +- */ ++ /* Start receiving IPIs and then read tlb_gen (and LAM below) */ + if (next != &init_mm) + cpumask_set_cpu(cpu, mm_cpumask(next)); + next_tlb_gen = atomic64_read(&next->context.tlb_gen); +@@ -633,6 +631,7 @@ void switch_mm_irqs_off(struct mm_struct *unused, struct mm_struct *next, + barrier(); + } + ++ new_lam = mm_lam_cr3_mask(next); + set_tlbstate_lam_mode(next); + if (need_flush) { + this_cpu_write(cpu_tlbstate.ctxs[new_asid].ctx_id, next->context.ctx_id); +diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c +index 5159c7a2292294..2f28a9b34b91e4 100644 +--- a/arch/x86/net/bpf_jit_comp.c ++++ b/arch/x86/net/bpf_jit_comp.c +@@ -273,7 +273,7 @@ struct jit_context { + /* Number of bytes emit_patch() needs to generate instructions */ + #define X86_PATCH_SIZE 5 + /* Number of bytes that will be skipped on tailcall */ +-#define X86_TAIL_CALL_OFFSET (11 + ENDBR_INSN_SIZE) ++#define X86_TAIL_CALL_OFFSET (12 + ENDBR_INSN_SIZE) + + static void push_r12(u8 **pprog) + { +@@ -403,6 +403,37 @@ static void emit_cfi(u8 **pprog, u32 hash) + *pprog = prog; + } + ++static void emit_prologue_tail_call(u8 **pprog, bool is_subprog) ++{ ++ u8 *prog = *pprog; ++ ++ if (!is_subprog) { ++ /* cmp rax, MAX_TAIL_CALL_CNT */ ++ EMIT4(0x48, 0x83, 0xF8, MAX_TAIL_CALL_CNT); ++ EMIT2(X86_JA, 6); /* ja 6 */ ++ /* rax is tail_call_cnt if <= MAX_TAIL_CALL_CNT. ++ * case1: entry of main prog. ++ * case2: tail callee of main prog. ++ */ ++ EMIT1(0x50); /* push rax */ ++ /* Make rax as tail_call_cnt_ptr. */ ++ EMIT3(0x48, 0x89, 0xE0); /* mov rax, rsp */ ++ EMIT2(0xEB, 1); /* jmp 1 */ ++ /* rax is tail_call_cnt_ptr if > MAX_TAIL_CALL_CNT. ++ * case: tail callee of subprog. ++ */ ++ EMIT1(0x50); /* push rax */ ++ /* push tail_call_cnt_ptr */ ++ EMIT1(0x50); /* push rax */ ++ } else { /* is_subprog */ ++ /* rax is tail_call_cnt_ptr. */ ++ EMIT1(0x50); /* push rax */ ++ EMIT1(0x50); /* push rax */ ++ } ++ ++ *pprog = prog; ++} ++ + /* + * Emit x86-64 prologue code for BPF program. + * bpf_tail_call helper will skip the first X86_TAIL_CALL_OFFSET bytes +@@ -424,10 +455,10 @@ static void emit_prologue(u8 **pprog, u32 stack_depth, bool ebpf_from_cbpf, + /* When it's the entry of the whole tailcall context, + * zeroing rax means initialising tail_call_cnt. + */ +- EMIT2(0x31, 0xC0); /* xor eax, eax */ ++ EMIT3(0x48, 0x31, 0xC0); /* xor rax, rax */ + else + /* Keep the same instruction layout. */ +- EMIT2(0x66, 0x90); /* nop2 */ ++ emit_nops(&prog, 3); /* nop3 */ + } + /* Exception callback receives FP as third parameter */ + if (is_exception_cb) { +@@ -453,7 +484,7 @@ static void emit_prologue(u8 **pprog, u32 stack_depth, bool ebpf_from_cbpf, + if (stack_depth) + EMIT3_off32(0x48, 0x81, 0xEC, round_up(stack_depth, 8)); + if (tail_call_reachable) +- EMIT1(0x50); /* push rax */ ++ emit_prologue_tail_call(&prog, is_subprog); + *pprog = prog; + } + +@@ -589,13 +620,15 @@ static void emit_return(u8 **pprog, u8 *ip) + *pprog = prog; + } + ++#define BPF_TAIL_CALL_CNT_PTR_STACK_OFF(stack) (-16 - round_up(stack, 8)) ++ + /* + * Generate the following code: + * + * ... bpf_tail_call(void *ctx, struct bpf_array *array, u64 index) ... + * if (index >= array->map.max_entries) + * goto out; +- * if (tail_call_cnt++ >= MAX_TAIL_CALL_CNT) ++ * if ((*tcc_ptr)++ >= MAX_TAIL_CALL_CNT) + * goto out; + * prog = array->ptrs[index]; + * if (prog == NULL) +@@ -608,7 +641,7 @@ static void emit_bpf_tail_call_indirect(struct bpf_prog *bpf_prog, + u32 stack_depth, u8 *ip, + struct jit_context *ctx) + { +- int tcc_off = -4 - round_up(stack_depth, 8); ++ int tcc_ptr_off = BPF_TAIL_CALL_CNT_PTR_STACK_OFF(stack_depth); + u8 *prog = *pprog, *start = *pprog; + int offset; + +@@ -630,16 +663,14 @@ static void emit_bpf_tail_call_indirect(struct bpf_prog *bpf_prog, + EMIT2(X86_JBE, offset); /* jbe out */ + + /* +- * if (tail_call_cnt++ >= MAX_TAIL_CALL_CNT) ++ * if ((*tcc_ptr)++ >= MAX_TAIL_CALL_CNT) + * goto out; + */ +- EMIT2_off32(0x8B, 0x85, tcc_off); /* mov eax, dword ptr [rbp - tcc_off] */ +- EMIT3(0x83, 0xF8, MAX_TAIL_CALL_CNT); /* cmp eax, MAX_TAIL_CALL_CNT */ ++ EMIT3_off32(0x48, 0x8B, 0x85, tcc_ptr_off); /* mov rax, qword ptr [rbp - tcc_ptr_off] */ ++ EMIT4(0x48, 0x83, 0x38, MAX_TAIL_CALL_CNT); /* cmp qword ptr [rax], MAX_TAIL_CALL_CNT */ + + offset = ctx->tail_call_indirect_label - (prog + 2 - start); + EMIT2(X86_JAE, offset); /* jae out */ +- EMIT3(0x83, 0xC0, 0x01); /* add eax, 1 */ +- EMIT2_off32(0x89, 0x85, tcc_off); /* mov dword ptr [rbp - tcc_off], eax */ + + /* prog = array->ptrs[index]; */ + EMIT4_off32(0x48, 0x8B, 0x8C, 0xD6, /* mov rcx, [rsi + rdx * 8 + offsetof(...)] */ +@@ -654,6 +685,9 @@ static void emit_bpf_tail_call_indirect(struct bpf_prog *bpf_prog, + offset = ctx->tail_call_indirect_label - (prog + 2 - start); + EMIT2(X86_JE, offset); /* je out */ + ++ /* Inc tail_call_cnt if the slot is populated. */ ++ EMIT4(0x48, 0x83, 0x00, 0x01); /* add qword ptr [rax], 1 */ ++ + if (bpf_prog->aux->exception_boundary) { + pop_callee_regs(&prog, all_callee_regs_used); + pop_r12(&prog); +@@ -663,6 +697,11 @@ static void emit_bpf_tail_call_indirect(struct bpf_prog *bpf_prog, + pop_r12(&prog); + } + ++ /* Pop tail_call_cnt_ptr. */ ++ EMIT1(0x58); /* pop rax */ ++ /* Pop tail_call_cnt, if it's main prog. ++ * Pop tail_call_cnt_ptr, if it's subprog. ++ */ + EMIT1(0x58); /* pop rax */ + if (stack_depth) + EMIT3_off32(0x48, 0x81, 0xC4, /* add rsp, sd */ +@@ -691,21 +730,19 @@ static void emit_bpf_tail_call_direct(struct bpf_prog *bpf_prog, + bool *callee_regs_used, u32 stack_depth, + struct jit_context *ctx) + { +- int tcc_off = -4 - round_up(stack_depth, 8); ++ int tcc_ptr_off = BPF_TAIL_CALL_CNT_PTR_STACK_OFF(stack_depth); + u8 *prog = *pprog, *start = *pprog; + int offset; + + /* +- * if (tail_call_cnt++ >= MAX_TAIL_CALL_CNT) ++ * if ((*tcc_ptr)++ >= MAX_TAIL_CALL_CNT) + * goto out; + */ +- EMIT2_off32(0x8B, 0x85, tcc_off); /* mov eax, dword ptr [rbp - tcc_off] */ +- EMIT3(0x83, 0xF8, MAX_TAIL_CALL_CNT); /* cmp eax, MAX_TAIL_CALL_CNT */ ++ EMIT3_off32(0x48, 0x8B, 0x85, tcc_ptr_off); /* mov rax, qword ptr [rbp - tcc_ptr_off] */ ++ EMIT4(0x48, 0x83, 0x38, MAX_TAIL_CALL_CNT); /* cmp qword ptr [rax], MAX_TAIL_CALL_CNT */ + + offset = ctx->tail_call_direct_label - (prog + 2 - start); + EMIT2(X86_JAE, offset); /* jae out */ +- EMIT3(0x83, 0xC0, 0x01); /* add eax, 1 */ +- EMIT2_off32(0x89, 0x85, tcc_off); /* mov dword ptr [rbp - tcc_off], eax */ + + poke->tailcall_bypass = ip + (prog - start); + poke->adj_off = X86_TAIL_CALL_OFFSET; +@@ -715,6 +752,9 @@ static void emit_bpf_tail_call_direct(struct bpf_prog *bpf_prog, + emit_jump(&prog, (u8 *)poke->tailcall_target + X86_PATCH_SIZE, + poke->tailcall_bypass); + ++ /* Inc tail_call_cnt if the slot is populated. */ ++ EMIT4(0x48, 0x83, 0x00, 0x01); /* add qword ptr [rax], 1 */ ++ + if (bpf_prog->aux->exception_boundary) { + pop_callee_regs(&prog, all_callee_regs_used); + pop_r12(&prog); +@@ -724,6 +764,11 @@ static void emit_bpf_tail_call_direct(struct bpf_prog *bpf_prog, + pop_r12(&prog); + } + ++ /* Pop tail_call_cnt_ptr. */ ++ EMIT1(0x58); /* pop rax */ ++ /* Pop tail_call_cnt, if it's main prog. ++ * Pop tail_call_cnt_ptr, if it's subprog. ++ */ + EMIT1(0x58); /* pop rax */ + if (stack_depth) + EMIT3_off32(0x48, 0x81, 0xC4, round_up(stack_depth, 8)); +@@ -1313,9 +1358,11 @@ static void emit_shiftx(u8 **pprog, u32 dst_reg, u8 src_reg, bool is64, u8 op) + + #define INSN_SZ_DIFF (((addrs[i] - addrs[i - 1]) - (prog - temp))) + +-/* mov rax, qword ptr [rbp - rounded_stack_depth - 8] */ +-#define RESTORE_TAIL_CALL_CNT(stack) \ +- EMIT3_off32(0x48, 0x8B, 0x85, -round_up(stack, 8) - 8) ++#define __LOAD_TCC_PTR(off) \ ++ EMIT3_off32(0x48, 0x8B, 0x85, off) ++/* mov rax, qword ptr [rbp - rounded_stack_depth - 16] */ ++#define LOAD_TAIL_CALL_CNT_PTR(stack) \ ++ __LOAD_TCC_PTR(BPF_TAIL_CALL_CNT_PTR_STACK_OFF(stack)) + + static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image, + int oldproglen, struct jit_context *ctx, bool jmp_padding) +@@ -2038,7 +2085,7 @@ st: if (is_imm8(insn->off)) + + func = (u8 *) __bpf_call_base + imm32; + if (tail_call_reachable) { +- RESTORE_TAIL_CALL_CNT(bpf_prog->aux->stack_depth); ++ LOAD_TAIL_CALL_CNT_PTR(bpf_prog->aux->stack_depth); + ip += 7; + } + if (!imm32) +@@ -2713,6 +2760,10 @@ static int invoke_bpf_mod_ret(const struct btf_func_model *m, u8 **pprog, + return 0; + } + ++/* mov rax, qword ptr [rbp - rounded_stack_depth - 8] */ ++#define LOAD_TRAMP_TAIL_CALL_CNT_PTR(stack) \ ++ __LOAD_TCC_PTR(-round_up(stack, 8) - 8) ++ + /* Example: + * __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev); + * its 'struct btf_func_model' will be nr_args=2 +@@ -2833,7 +2884,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im + * [ ... ] + * [ stack_arg2 ] + * RBP - arg_stack_off [ stack_arg1 ] +- * RSP [ tail_call_cnt ] BPF_TRAMP_F_TAIL_CALL_CTX ++ * RSP [ tail_call_cnt_ptr ] BPF_TRAMP_F_TAIL_CALL_CTX + */ + + /* room for return value of orig_call or fentry prog */ +@@ -2962,10 +3013,10 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im + save_args(m, &prog, arg_stack_off, true); + + if (flags & BPF_TRAMP_F_TAIL_CALL_CTX) { +- /* Before calling the original function, restore the +- * tail_call_cnt from stack to rax. ++ /* Before calling the original function, load the ++ * tail_call_cnt_ptr from stack to rax. + */ +- RESTORE_TAIL_CALL_CNT(stack_size); ++ LOAD_TRAMP_TAIL_CALL_CNT_PTR(stack_size); + } + + if (flags & BPF_TRAMP_F_ORIG_STACK) { +@@ -3024,10 +3075,10 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im + goto cleanup; + } + } else if (flags & BPF_TRAMP_F_TAIL_CALL_CTX) { +- /* Before running the original function, restore the +- * tail_call_cnt from stack to rax. ++ /* Before running the original function, load the ++ * tail_call_cnt_ptr from stack to rax. + */ +- RESTORE_TAIL_CALL_CNT(stack_size); ++ LOAD_TRAMP_TAIL_CALL_CNT_PTR(stack_size); + } + + /* restore return value of orig_call or fentry prog back into RAX */ +diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c +index b33afb240601b0..98a9bb92d75c88 100644 +--- a/arch/x86/pci/fixup.c ++++ b/arch/x86/pci/fixup.c +@@ -980,7 +980,7 @@ static void amd_rp_pme_suspend(struct pci_dev *dev) + return; + + rp = pcie_find_root_port(dev); +- if (!rp->pm_cap) ++ if (!rp || !rp->pm_cap) + return; + + rp->pme_support &= ~((PCI_PM_CAP_PME_D3hot|PCI_PM_CAP_PME_D3cold) >> +@@ -994,7 +994,7 @@ static void amd_rp_pme_resume(struct pci_dev *dev) + u16 pmc; + + rp = pcie_find_root_port(dev); +- if (!rp->pm_cap) ++ if (!rp || !rp->pm_cap) + return; + + pci_read_config_word(rp, rp->pm_cap + PCI_PM_PMC, &pmc); +diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c +index 54e0d311dcc94a..9e9a122c2bcfac 100644 +--- a/arch/x86/xen/mmu_pv.c ++++ b/arch/x86/xen/mmu_pv.c +@@ -2019,10 +2019,7 @@ void __init xen_reserve_special_pages(void) + + void __init xen_pt_check_e820(void) + { +- if (xen_is_e820_reserved(xen_pt_base, xen_pt_size)) { +- xen_raw_console_write("Xen hypervisor allocated page table memory conflicts with E820 map\n"); +- BUG(); +- } ++ xen_chk_is_e820_usable(xen_pt_base, xen_pt_size, "page table"); + } + + static unsigned char dummy_mapping[PAGE_SIZE] __page_aligned_bss; +diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c +index 6bcbdf3b7999fd..d8f175ee9248f6 100644 +--- a/arch/x86/xen/p2m.c ++++ b/arch/x86/xen/p2m.c +@@ -70,6 +70,7 @@ + #include <linux/memblock.h> + #include <linux/slab.h> + #include <linux/vmalloc.h> ++#include <linux/acpi.h> + + #include <asm/cache.h> + #include <asm/setup.h> +@@ -80,6 +81,7 @@ + #include <asm/xen/hypervisor.h> + #include <xen/balloon.h> + #include <xen/grant_table.h> ++#include <xen/hvc-console.h> + + #include "multicalls.h" + #include "xen-ops.h" +@@ -793,6 +795,102 @@ int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops, + return ret; + } + ++/* Remapped non-RAM areas */ ++#define NR_NONRAM_REMAP 4 ++static struct nonram_remap { ++ phys_addr_t maddr; ++ phys_addr_t paddr; ++ size_t size; ++} xen_nonram_remap[NR_NONRAM_REMAP] __ro_after_init; ++static unsigned int nr_nonram_remap __ro_after_init; ++ ++/* ++ * Do the real remapping of non-RAM regions as specified in the ++ * xen_nonram_remap[] array. ++ * In case of an error just crash the system. ++ */ ++void __init xen_do_remap_nonram(void) ++{ ++ unsigned int i; ++ unsigned int remapped = 0; ++ const struct nonram_remap *remap = xen_nonram_remap; ++ unsigned long pfn, mfn, end_pfn; ++ ++ for (i = 0; i < nr_nonram_remap; i++) { ++ end_pfn = PFN_UP(remap->paddr + remap->size); ++ pfn = PFN_DOWN(remap->paddr); ++ mfn = PFN_DOWN(remap->maddr); ++ while (pfn < end_pfn) { ++ if (!set_phys_to_machine(pfn, mfn)) ++ panic("Failed to set p2m mapping for pfn=%lx mfn=%lx\n", ++ pfn, mfn); ++ ++ pfn++; ++ mfn++; ++ remapped++; ++ } ++ ++ remap++; ++ } ++ ++ pr_info("Remapped %u non-RAM page(s)\n", remapped); ++} ++ ++#ifdef CONFIG_ACPI ++/* ++ * Xen variant of acpi_os_ioremap() taking potentially remapped non-RAM ++ * regions into account. ++ * Any attempt to map an area crossing a remap boundary will produce a ++ * WARN() splat. ++ * phys is related to remap->maddr on input and will be rebased to remap->paddr. ++ */ ++static void __iomem *xen_acpi_os_ioremap(acpi_physical_address phys, ++ acpi_size size) ++{ ++ unsigned int i; ++ const struct nonram_remap *remap = xen_nonram_remap; ++ ++ for (i = 0; i < nr_nonram_remap; i++) { ++ if (phys + size > remap->maddr && ++ phys < remap->maddr + remap->size) { ++ WARN_ON(phys < remap->maddr || ++ phys + size > remap->maddr + remap->size); ++ phys += remap->paddr - remap->maddr; ++ break; ++ } ++ } ++ ++ return x86_acpi_os_ioremap(phys, size); ++} ++#endif /* CONFIG_ACPI */ ++ ++/* ++ * Add a new non-RAM remap entry. ++ * In case of no free entry found, just crash the system. ++ */ ++void __init xen_add_remap_nonram(phys_addr_t maddr, phys_addr_t paddr, ++ unsigned long size) ++{ ++ BUG_ON((maddr & ~PAGE_MASK) != (paddr & ~PAGE_MASK)); ++ ++ if (nr_nonram_remap == NR_NONRAM_REMAP) { ++ xen_raw_console_write("Number of required E820 entry remapping actions exceed maximum value\n"); ++ BUG(); ++ } ++ ++#ifdef CONFIG_ACPI ++ /* Switch to the Xen acpi_os_ioremap() variant. */ ++ if (nr_nonram_remap == 0) ++ acpi_os_ioremap = xen_acpi_os_ioremap; ++#endif ++ ++ xen_nonram_remap[nr_nonram_remap].maddr = maddr; ++ xen_nonram_remap[nr_nonram_remap].paddr = paddr; ++ xen_nonram_remap[nr_nonram_remap].size = size; ++ ++ nr_nonram_remap++; ++} ++ + #ifdef CONFIG_XEN_DEBUG_FS + #include <linux/debugfs.h> + #include "debugfs.h" +diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c +index 380591028cb8f4..dc822124cacb9c 100644 +--- a/arch/x86/xen/setup.c ++++ b/arch/x86/xen/setup.c +@@ -15,12 +15,12 @@ + #include <linux/cpuidle.h> + #include <linux/cpufreq.h> + #include <linux/memory_hotplug.h> ++#include <linux/acpi.h> + + #include <asm/elf.h> + #include <asm/vdso.h> + #include <asm/e820/api.h> + #include <asm/setup.h> +-#include <asm/acpi.h> + #include <asm/numa.h> + #include <asm/idtentry.h> + #include <asm/xen/hypervisor.h> +@@ -47,6 +47,9 @@ bool xen_pv_pci_possible; + /* E820 map used during setting up memory. */ + static struct e820_table xen_e820_table __initdata; + ++/* Number of initially usable memory pages. */ ++static unsigned long ini_nr_pages __initdata; ++ + /* + * Buffer used to remap identity mapped pages. We only need the virtual space. + * The physical page behind this address is remapped as needed to different +@@ -213,7 +216,7 @@ static int __init xen_free_mfn(unsigned long mfn) + * as a fallback if the remapping fails. + */ + static void __init xen_set_identity_and_release_chunk(unsigned long start_pfn, +- unsigned long end_pfn, unsigned long nr_pages) ++ unsigned long end_pfn) + { + unsigned long pfn, end; + int ret; +@@ -221,7 +224,7 @@ static void __init xen_set_identity_and_release_chunk(unsigned long start_pfn, + WARN_ON(start_pfn > end_pfn); + + /* Release pages first. */ +- end = min(end_pfn, nr_pages); ++ end = min(end_pfn, ini_nr_pages); + for (pfn = start_pfn; pfn < end; pfn++) { + unsigned long mfn = pfn_to_mfn(pfn); + +@@ -342,15 +345,14 @@ static void __init xen_do_set_identity_and_remap_chunk( + * to Xen and not remapped. + */ + static unsigned long __init xen_set_identity_and_remap_chunk( +- unsigned long start_pfn, unsigned long end_pfn, unsigned long nr_pages, +- unsigned long remap_pfn) ++ unsigned long start_pfn, unsigned long end_pfn, unsigned long remap_pfn) + { + unsigned long pfn; + unsigned long i = 0; + unsigned long n = end_pfn - start_pfn; + + if (remap_pfn == 0) +- remap_pfn = nr_pages; ++ remap_pfn = ini_nr_pages; + + while (i < n) { + unsigned long cur_pfn = start_pfn + i; +@@ -359,19 +361,19 @@ static unsigned long __init xen_set_identity_and_remap_chunk( + unsigned long remap_range_size; + + /* Do not remap pages beyond the current allocation */ +- if (cur_pfn >= nr_pages) { ++ if (cur_pfn >= ini_nr_pages) { + /* Identity map remaining pages */ + set_phys_range_identity(cur_pfn, cur_pfn + size); + break; + } +- if (cur_pfn + size > nr_pages) +- size = nr_pages - cur_pfn; ++ if (cur_pfn + size > ini_nr_pages) ++ size = ini_nr_pages - cur_pfn; + + remap_range_size = xen_find_pfn_range(&remap_pfn); + if (!remap_range_size) { + pr_warn("Unable to find available pfn range, not remapping identity pages\n"); + xen_set_identity_and_release_chunk(cur_pfn, +- cur_pfn + left, nr_pages); ++ cur_pfn + left); + break; + } + /* Adjust size to fit in current e820 RAM region */ +@@ -398,18 +400,18 @@ static unsigned long __init xen_set_identity_and_remap_chunk( + } + + static unsigned long __init xen_count_remap_pages( +- unsigned long start_pfn, unsigned long end_pfn, unsigned long nr_pages, ++ unsigned long start_pfn, unsigned long end_pfn, + unsigned long remap_pages) + { +- if (start_pfn >= nr_pages) ++ if (start_pfn >= ini_nr_pages) + return remap_pages; + +- return remap_pages + min(end_pfn, nr_pages) - start_pfn; ++ return remap_pages + min(end_pfn, ini_nr_pages) - start_pfn; + } + +-static unsigned long __init xen_foreach_remap_area(unsigned long nr_pages, ++static unsigned long __init xen_foreach_remap_area( + unsigned long (*func)(unsigned long start_pfn, unsigned long end_pfn, +- unsigned long nr_pages, unsigned long last_val)) ++ unsigned long last_val)) + { + phys_addr_t start = 0; + unsigned long ret_val = 0; +@@ -437,8 +439,7 @@ static unsigned long __init xen_foreach_remap_area(unsigned long nr_pages, + end_pfn = PFN_UP(entry->addr); + + if (start_pfn < end_pfn) +- ret_val = func(start_pfn, end_pfn, nr_pages, +- ret_val); ++ ret_val = func(start_pfn, end_pfn, ret_val); + start = end; + } + } +@@ -495,6 +496,8 @@ void __init xen_remap_memory(void) + set_pte_mfn(buf, mfn_save, PAGE_KERNEL); + + pr_info("Remapped %ld page(s)\n", remapped); ++ ++ xen_do_remap_nonram(); + } + + static unsigned long __init xen_get_pages_limit(void) +@@ -568,7 +571,7 @@ static void __init xen_ignore_unusable(void) + } + } + +-bool __init xen_is_e820_reserved(phys_addr_t start, phys_addr_t size) ++static bool __init xen_is_e820_reserved(phys_addr_t start, phys_addr_t size) + { + struct e820_entry *entry; + unsigned mapcnt; +@@ -625,6 +628,111 @@ phys_addr_t __init xen_find_free_area(phys_addr_t size) + return 0; + } + ++/* ++ * Swap a non-RAM E820 map entry with RAM above ini_nr_pages. ++ * Note that the E820 map is modified accordingly, but the P2M map isn't yet. ++ * The adaption of the P2M must be deferred until page allocation is possible. ++ */ ++static void __init xen_e820_swap_entry_with_ram(struct e820_entry *swap_entry) ++{ ++ struct e820_entry *entry; ++ unsigned int mapcnt; ++ phys_addr_t mem_end = PFN_PHYS(ini_nr_pages); ++ phys_addr_t swap_addr, swap_size, entry_end; ++ ++ swap_addr = PAGE_ALIGN_DOWN(swap_entry->addr); ++ swap_size = PAGE_ALIGN(swap_entry->addr - swap_addr + swap_entry->size); ++ entry = xen_e820_table.entries; ++ ++ for (mapcnt = 0; mapcnt < xen_e820_table.nr_entries; mapcnt++) { ++ entry_end = entry->addr + entry->size; ++ if (entry->type == E820_TYPE_RAM && entry->size >= swap_size && ++ entry_end - swap_size >= mem_end) { ++ /* Reduce RAM entry by needed space (whole pages). */ ++ entry->size -= swap_size; ++ ++ /* Add new entry at the end of E820 map. */ ++ entry = xen_e820_table.entries + ++ xen_e820_table.nr_entries; ++ xen_e820_table.nr_entries++; ++ ++ /* Fill new entry (keep size and page offset). */ ++ entry->type = swap_entry->type; ++ entry->addr = entry_end - swap_size + ++ swap_addr - swap_entry->addr; ++ entry->size = swap_entry->size; ++ ++ /* Convert old entry to RAM, align to pages. */ ++ swap_entry->type = E820_TYPE_RAM; ++ swap_entry->addr = swap_addr; ++ swap_entry->size = swap_size; ++ ++ /* Remember PFN<->MFN relation for P2M update. */ ++ xen_add_remap_nonram(swap_addr, entry_end - swap_size, ++ swap_size); ++ ++ /* Order E820 table and merge entries. */ ++ e820__update_table(&xen_e820_table); ++ ++ return; ++ } ++ ++ entry++; ++ } ++ ++ xen_raw_console_write("No suitable area found for required E820 entry remapping action\n"); ++ BUG(); ++} ++ ++/* ++ * Look for non-RAM memory types in a specific guest physical area and move ++ * those away if possible (ACPI NVS only for now). ++ */ ++static void __init xen_e820_resolve_conflicts(phys_addr_t start, ++ phys_addr_t size) ++{ ++ struct e820_entry *entry; ++ unsigned int mapcnt; ++ phys_addr_t end; ++ ++ if (!size) ++ return; ++ ++ end = start + size; ++ entry = xen_e820_table.entries; ++ ++ for (mapcnt = 0; mapcnt < xen_e820_table.nr_entries; mapcnt++) { ++ if (entry->addr >= end) ++ return; ++ ++ if (entry->addr + entry->size > start && ++ entry->type == E820_TYPE_NVS) ++ xen_e820_swap_entry_with_ram(entry); ++ ++ entry++; ++ } ++} ++ ++/* ++ * Check for an area in physical memory to be usable for non-movable purposes. ++ * An area is considered to usable if the used E820 map lists it to be RAM or ++ * some other type which can be moved to higher PFNs while keeping the MFNs. ++ * In case the area is not usable, crash the system with an error message. ++ */ ++void __init xen_chk_is_e820_usable(phys_addr_t start, phys_addr_t size, ++ const char *component) ++{ ++ xen_e820_resolve_conflicts(start, size); ++ ++ if (!xen_is_e820_reserved(start, size)) ++ return; ++ ++ xen_raw_console_write("Xen hypervisor allocated "); ++ xen_raw_console_write(component); ++ xen_raw_console_write(" memory conflicts with E820 map\n"); ++ BUG(); ++} ++ + /* + * Like memcpy, but with physical addresses for dest and src. + */ +@@ -684,20 +792,20 @@ static void __init xen_reserve_xen_mfnlist(void) + **/ + char * __init xen_memory_setup(void) + { +- unsigned long max_pfn, pfn_s, n_pfns; ++ unsigned long pfn_s, n_pfns; + phys_addr_t mem_end, addr, size, chunk_size; + u32 type; + int rc; + struct xen_memory_map memmap; + unsigned long max_pages; + unsigned long extra_pages = 0; ++ unsigned long maxmem_pages; + int i; + int op; + + xen_parse_512gb(); +- max_pfn = xen_get_pages_limit(); +- max_pfn = min(max_pfn, xen_start_info->nr_pages); +- mem_end = PFN_PHYS(max_pfn); ++ ini_nr_pages = min(xen_get_pages_limit(), xen_start_info->nr_pages); ++ mem_end = PFN_PHYS(ini_nr_pages); + + memmap.nr_entries = ARRAY_SIZE(xen_e820_table.entries); + set_xen_guest_handle(memmap.buffer, xen_e820_table.entries); +@@ -747,13 +855,35 @@ char * __init xen_memory_setup(void) + /* Make sure the Xen-supplied memory map is well-ordered. */ + e820__update_table(&xen_e820_table); + ++ /* ++ * Check whether the kernel itself conflicts with the target E820 map. ++ * Failing now is better than running into weird problems later due ++ * to relocating (and even reusing) pages with kernel text or data. ++ */ ++ xen_chk_is_e820_usable(__pa_symbol(_text), ++ __pa_symbol(_end) - __pa_symbol(_text), ++ "kernel"); ++ ++ /* ++ * Check for a conflict of the xen_start_info memory with the target ++ * E820 map. ++ */ ++ xen_chk_is_e820_usable(__pa(xen_start_info), sizeof(*xen_start_info), ++ "xen_start_info"); ++ ++ /* ++ * Check for a conflict of the hypervisor supplied page tables with ++ * the target E820 map. ++ */ ++ xen_pt_check_e820(); ++ + max_pages = xen_get_max_pages(); + + /* How many extra pages do we need due to remapping? */ +- max_pages += xen_foreach_remap_area(max_pfn, xen_count_remap_pages); ++ max_pages += xen_foreach_remap_area(xen_count_remap_pages); + +- if (max_pages > max_pfn) +- extra_pages += max_pages - max_pfn; ++ if (max_pages > ini_nr_pages) ++ extra_pages += max_pages - ini_nr_pages; + + /* + * Clamp the amount of extra memory to a EXTRA_MEM_RATIO +@@ -762,8 +892,8 @@ char * __init xen_memory_setup(void) + * Make sure we have no memory above max_pages, as this area + * isn't handled by the p2m management. + */ +- extra_pages = min3(EXTRA_MEM_RATIO * min(max_pfn, PFN_DOWN(MAXMEM)), +- extra_pages, max_pages - max_pfn); ++ maxmem_pages = EXTRA_MEM_RATIO * min(ini_nr_pages, PFN_DOWN(MAXMEM)); ++ extra_pages = min3(maxmem_pages, extra_pages, max_pages - ini_nr_pages); + i = 0; + addr = xen_e820_table.entries[0].addr; + size = xen_e820_table.entries[0].size; +@@ -819,23 +949,6 @@ char * __init xen_memory_setup(void) + + e820__update_table(e820_table); + +- /* +- * Check whether the kernel itself conflicts with the target E820 map. +- * Failing now is better than running into weird problems later due +- * to relocating (and even reusing) pages with kernel text or data. +- */ +- if (xen_is_e820_reserved(__pa_symbol(_text), +- __pa_symbol(__bss_stop) - __pa_symbol(_text))) { +- xen_raw_console_write("Xen hypervisor allocated kernel memory conflicts with E820 map\n"); +- BUG(); +- } +- +- /* +- * Check for a conflict of the hypervisor supplied page tables with +- * the target E820 map. +- */ +- xen_pt_check_e820(); +- + xen_reserve_xen_mfnlist(); + + /* Check for a conflict of the initrd with the target E820 map. */ +@@ -863,7 +976,7 @@ char * __init xen_memory_setup(void) + * Set identity map on non-RAM pages and prepare remapping the + * underlying RAM. + */ +- xen_foreach_remap_area(max_pfn, xen_set_identity_and_remap_chunk); ++ xen_foreach_remap_area(xen_set_identity_and_remap_chunk); + + pr_info("Released %ld page(s)\n", xen_released_pages); + +diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h +index 79cf93f2c92f1d..a6a21dd0552700 100644 +--- a/arch/x86/xen/xen-ops.h ++++ b/arch/x86/xen/xen-ops.h +@@ -43,8 +43,12 @@ void xen_mm_unpin_all(void); + #ifdef CONFIG_X86_64 + void __init xen_relocate_p2m(void); + #endif ++void __init xen_do_remap_nonram(void); ++void __init xen_add_remap_nonram(phys_addr_t maddr, phys_addr_t paddr, ++ unsigned long size); + +-bool __init xen_is_e820_reserved(phys_addr_t start, phys_addr_t size); ++void __init xen_chk_is_e820_usable(phys_addr_t start, phys_addr_t size, ++ const char *component); + unsigned long __ref xen_chk_extra_mem(unsigned long pfn); + void __init xen_inv_extra_mem(void); + void __init xen_remap_memory(void); +diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c +index 4b88a54a9b76cb..05372a78cd5161 100644 +--- a/block/bfq-iosched.c ++++ b/block/bfq-iosched.c +@@ -2911,8 +2911,12 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq, + struct bfq_iocq_bfqq_data *bfqq_data = &bic->bfqq_data[a_idx]; + + /* if a merge has already been setup, then proceed with that first */ +- if (bfqq->new_bfqq) +- return bfqq->new_bfqq; ++ new_bfqq = bfqq->new_bfqq; ++ if (new_bfqq) { ++ while (new_bfqq->new_bfqq) ++ new_bfqq = new_bfqq->new_bfqq; ++ return new_bfqq; ++ } + + /* + * Check delayed stable merge for rotational or non-queueing +@@ -3125,10 +3129,12 @@ void bfq_release_process_ref(struct bfq_data *bfqd, struct bfq_queue *bfqq) + bfq_put_queue(bfqq); + } + +-static void +-bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic, +- struct bfq_queue *bfqq, struct bfq_queue *new_bfqq) ++static struct bfq_queue *bfq_merge_bfqqs(struct bfq_data *bfqd, ++ struct bfq_io_cq *bic, ++ struct bfq_queue *bfqq) + { ++ struct bfq_queue *new_bfqq = bfqq->new_bfqq; ++ + bfq_log_bfqq(bfqd, bfqq, "merging with queue %lu", + (unsigned long)new_bfqq->pid); + /* Save weight raising and idle window of the merged queues */ +@@ -3222,6 +3228,8 @@ bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic, + bfq_reassign_last_bfqq(bfqq, new_bfqq); + + bfq_release_process_ref(bfqd, bfqq); ++ ++ return new_bfqq; + } + + static bool bfq_allow_bio_merge(struct request_queue *q, struct request *rq, +@@ -3257,14 +3265,8 @@ static bool bfq_allow_bio_merge(struct request_queue *q, struct request *rq, + * fulfilled, i.e., bic can be redirected to new_bfqq + * and bfqq can be put. + */ +- bfq_merge_bfqqs(bfqd, bfqd->bio_bic, bfqq, +- new_bfqq); +- /* +- * If we get here, bio will be queued into new_queue, +- * so use new_bfqq to decide whether bio and rq can be +- * merged. +- */ +- bfqq = new_bfqq; ++ while (bfqq != new_bfqq) ++ bfqq = bfq_merge_bfqqs(bfqd, bfqd->bio_bic, bfqq); + + /* + * Change also bqfd->bio_bfqq, as +@@ -5699,9 +5701,7 @@ bfq_do_early_stable_merge(struct bfq_data *bfqd, struct bfq_queue *bfqq, + * state before killing it. + */ + bfqq->bic = bic; +- bfq_merge_bfqqs(bfqd, bic, bfqq, new_bfqq); +- +- return new_bfqq; ++ return bfq_merge_bfqqs(bfqd, bic, bfqq); + } + + /* +@@ -6156,6 +6156,7 @@ static bool __bfq_insert_request(struct bfq_data *bfqd, struct request *rq) + bool waiting, idle_timer_disabled = false; + + if (new_bfqq) { ++ struct bfq_queue *old_bfqq = bfqq; + /* + * Release the request's reference to the old bfqq + * and make sure one is taken to the shared queue. +@@ -6172,18 +6173,18 @@ static bool __bfq_insert_request(struct bfq_data *bfqd, struct request *rq) + * new_bfqq. + */ + if (bic_to_bfqq(RQ_BIC(rq), true, +- bfq_actuator_index(bfqd, rq->bio)) == bfqq) +- bfq_merge_bfqqs(bfqd, RQ_BIC(rq), +- bfqq, new_bfqq); ++ bfq_actuator_index(bfqd, rq->bio)) == bfqq) { ++ while (bfqq != new_bfqq) ++ bfqq = bfq_merge_bfqqs(bfqd, RQ_BIC(rq), bfqq); ++ } + +- bfq_clear_bfqq_just_created(bfqq); ++ bfq_clear_bfqq_just_created(old_bfqq); + /* + * rq is about to be enqueued into new_bfqq, + * release rq reference on bfqq + */ +- bfq_put_queue(bfqq); ++ bfq_put_queue(old_bfqq); + rq->elv.priv[1] = new_bfqq; +- bfqq = new_bfqq; + } + + bfq_update_io_thinktime(bfqd, bfqq); +@@ -6721,7 +6722,7 @@ bfq_split_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq) + { + bfq_log_bfqq(bfqq->bfqd, bfqq, "splitting queue"); + +- if (bfqq_process_refs(bfqq) == 1) { ++ if (bfqq_process_refs(bfqq) == 1 && !bfqq->new_bfqq) { + bfqq->pid = current->pid; + bfq_clear_bfqq_coop(bfqq); + bfq_clear_bfqq_split_coop(bfqq); +@@ -6819,6 +6820,31 @@ static void bfq_prepare_request(struct request *rq) + rq->elv.priv[0] = rq->elv.priv[1] = NULL; + } + ++static struct bfq_queue *bfq_waker_bfqq(struct bfq_queue *bfqq) ++{ ++ struct bfq_queue *new_bfqq = bfqq->new_bfqq; ++ struct bfq_queue *waker_bfqq = bfqq->waker_bfqq; ++ ++ if (!waker_bfqq) ++ return NULL; ++ ++ while (new_bfqq) { ++ if (new_bfqq == waker_bfqq) { ++ /* ++ * If waker_bfqq is in the merge chain, and current ++ * is the only procress. ++ */ ++ if (bfqq_process_refs(waker_bfqq) == 1) ++ return NULL; ++ break; ++ } ++ ++ new_bfqq = new_bfqq->new_bfqq; ++ } ++ ++ return waker_bfqq; ++} ++ + /* + * If needed, init rq, allocate bfq data structures associated with + * rq, and increment reference counters in the destination bfq_queue +@@ -6880,7 +6906,7 @@ static struct bfq_queue *bfq_init_rq(struct request *rq) + /* If the queue was seeky for too long, break it apart. */ + if (bfq_bfqq_coop(bfqq) && bfq_bfqq_split_coop(bfqq) && + !bic->bfqq_data[a_idx].stably_merged) { +- struct bfq_queue *old_bfqq = bfqq; ++ struct bfq_queue *waker_bfqq = bfq_waker_bfqq(bfqq); + + /* Update bic before losing reference to bfqq */ + if (bfq_bfqq_in_large_burst(bfqq)) +@@ -6900,7 +6926,7 @@ static struct bfq_queue *bfq_init_rq(struct request *rq) + bfqq_already_existing = true; + + if (!bfqq_already_existing) { +- bfqq->waker_bfqq = old_bfqq->waker_bfqq; ++ bfqq->waker_bfqq = waker_bfqq; + bfqq->tentative_waker_bfqq = NULL; + + /* +@@ -6910,7 +6936,7 @@ static struct bfq_queue *bfq_init_rq(struct request *rq) + * woken_list of the waker. See + * bfq_check_waker for details. + */ +- if (bfqq->waker_bfqq) ++ if (waker_bfqq) + hlist_add_head(&bfqq->woken_list_node, + &bfqq->waker_bfqq->woken_list); + } +@@ -6932,7 +6958,8 @@ static struct bfq_queue *bfq_init_rq(struct request *rq) + * addition, if the queue has also just been split, we have to + * resume its state. + */ +- if (likely(bfqq != &bfqd->oom_bfqq) && bfqq_process_refs(bfqq) == 1) { ++ if (likely(bfqq != &bfqd->oom_bfqq) && !bfqq->new_bfqq && ++ bfqq_process_refs(bfqq) == 1) { + bfqq->bic = bic; + if (split) { + /* +diff --git a/block/partitions/core.c b/block/partitions/core.c +index ab76e64f0f6c3b..5bd7a603092ea9 100644 +--- a/block/partitions/core.c ++++ b/block/partitions/core.c +@@ -555,9 +555,11 @@ static bool blk_add_partition(struct gendisk *disk, + + part = add_partition(disk, p, from, size, state->parts[p].flags, + &state->parts[p].info); +- if (IS_ERR(part) && PTR_ERR(part) != -ENXIO) { +- printk(KERN_ERR " %s: p%d could not be added: %pe\n", +- disk->disk_name, p, part); ++ if (IS_ERR(part)) { ++ if (PTR_ERR(part) != -ENXIO) { ++ printk(KERN_ERR " %s: p%d could not be added: %pe\n", ++ disk->disk_name, p, part); ++ } + return true; + } + +diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c +index a5da8ccd353ef7..43af5fa510c09f 100644 +--- a/crypto/asymmetric_keys/asymmetric_type.c ++++ b/crypto/asymmetric_keys/asymmetric_type.c +@@ -60,17 +60,18 @@ struct key *find_asymmetric_key(struct key *keyring, + char *req, *p; + int len; + +- WARN_ON(!id_0 && !id_1 && !id_2); +- + if (id_0) { + lookup = id_0->data; + len = id_0->len; + } else if (id_1) { + lookup = id_1->data; + len = id_1->len; +- } else { ++ } else if (id_2) { + lookup = id_2->data; + len = id_2->len; ++ } else { ++ WARN_ON(1); ++ return ERR_PTR(-EINVAL); + } + + /* Construct an identifier "id:<keyid>". */ +diff --git a/crypto/xor.c b/crypto/xor.c +index 8e72e5d5db0ded..56aa3169e87171 100644 +--- a/crypto/xor.c ++++ b/crypto/xor.c +@@ -83,33 +83,30 @@ static void __init + do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2) + { + int speed; +- int i, j; +- ktime_t min, start, diff; ++ unsigned long reps; ++ ktime_t min, start, t0; + + tmpl->next = template_list; + template_list = tmpl; + + preempt_disable(); + +- min = (ktime_t)S64_MAX; +- for (i = 0; i < 3; i++) { +- start = ktime_get(); +- for (j = 0; j < REPS; j++) { +- mb(); /* prevent loop optimization */ +- tmpl->do_2(BENCH_SIZE, b1, b2); +- mb(); +- } +- diff = ktime_sub(ktime_get(), start); +- if (diff < min) +- min = diff; +- } ++ reps = 0; ++ t0 = ktime_get(); ++ /* delay start until time has advanced */ ++ while ((start = ktime_get()) == t0) ++ cpu_relax(); ++ do { ++ mb(); /* prevent loop optimization */ ++ tmpl->do_2(BENCH_SIZE, b1, b2); ++ mb(); ++ } while (reps++ < REPS || (t0 = ktime_get()) == start); ++ min = ktime_sub(t0, start); + + preempt_enable(); + + // bytes/ns == GB/s, multiply by 1000 to get MB/s [not MiB/s] +- if (!min) +- min = 1; +- speed = (1000 * REPS * BENCH_SIZE) / (unsigned int)ktime_to_ns(min); ++ speed = (1000 * reps * BENCH_SIZE) / (unsigned int)ktime_to_ns(min); + tmpl->speed = speed; + + pr_info(" %-16s: %5d MB/sec\n", tmpl->name, speed); +diff --git a/drivers/acpi/acpica/exsystem.c b/drivers/acpi/acpica/exsystem.c +index f665ffd9a396cf..2c384bd52b9c4b 100644 +--- a/drivers/acpi/acpica/exsystem.c ++++ b/drivers/acpi/acpica/exsystem.c +@@ -133,14 +133,15 @@ acpi_status acpi_ex_system_do_stall(u32 how_long_us) + * (ACPI specifies 100 usec as max, but this gives some slack in + * order to support existing BIOSs) + */ +- ACPI_ERROR((AE_INFO, +- "Time parameter is too large (%u)", how_long_us)); ++ ACPI_ERROR_ONCE((AE_INFO, ++ "Time parameter is too large (%u)", ++ how_long_us)); + status = AE_AML_OPERAND_VALUE; + } else { + if (how_long_us > 100) { +- ACPI_WARNING((AE_INFO, +- "Time parameter %u us > 100 us violating ACPI spec, please fix the firmware.", +- how_long_us)); ++ ACPI_WARNING_ONCE((AE_INFO, ++ "Time parameter %u us > 100 us violating ACPI spec, please fix the firmware.", ++ how_long_us)); + } + acpi_os_stall(how_long_us); + } +diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c +index 1d857978f5f407..2a588e4ed4af44 100644 +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -170,8 +170,11 @@ show_cppc_data(cppc_get_perf_ctrs, cppc_perf_fb_ctrs, wraparound_time); + #define GET_BIT_WIDTH(reg) ((reg)->access_width ? (8 << ((reg)->access_width - 1)) : (reg)->bit_width) + + /* Shift and apply the mask for CPC reads/writes */ +-#define MASK_VAL(reg, val) (((val) >> (reg)->bit_offset) & \ ++#define MASK_VAL_READ(reg, val) (((val) >> (reg)->bit_offset) & \ + GENMASK(((reg)->bit_width) - 1, 0)) ++#define MASK_VAL_WRITE(reg, prev_val, val) \ ++ ((((val) & GENMASK(((reg)->bit_width) - 1, 0)) << (reg)->bit_offset) | \ ++ ((prev_val) & ~(GENMASK(((reg)->bit_width) - 1, 0) << (reg)->bit_offset))) \ + + static ssize_t show_feedback_ctrs(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +@@ -857,6 +860,7 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr) + + /* Store CPU Logical ID */ + cpc_ptr->cpu_id = pr->id; ++ spin_lock_init(&cpc_ptr->rmw_lock); + + /* Parse PSD data for this CPU */ + ret = acpi_get_psd(cpc_ptr, handle); +@@ -1062,7 +1066,7 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val) + } + + if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) +- *val = MASK_VAL(reg, *val); ++ *val = MASK_VAL_READ(reg, *val); + + return 0; + } +@@ -1071,9 +1075,11 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val) + { + int ret_val = 0; + int size; ++ u64 prev_val; + void __iomem *vaddr = NULL; + int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu); + struct cpc_reg *reg = ®_res->cpc_entry.reg; ++ struct cpc_desc *cpc_desc; + + size = GET_BIT_WIDTH(reg); + +@@ -1106,8 +1112,34 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val) + return acpi_os_write_memory((acpi_physical_address)reg->address, + val, size); + +- if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) +- val = MASK_VAL(reg, val); ++ if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { ++ cpc_desc = per_cpu(cpc_desc_ptr, cpu); ++ if (!cpc_desc) { ++ pr_debug("No CPC descriptor for CPU:%d\n", cpu); ++ return -ENODEV; ++ } ++ ++ spin_lock(&cpc_desc->rmw_lock); ++ switch (size) { ++ case 8: ++ prev_val = readb_relaxed(vaddr); ++ break; ++ case 16: ++ prev_val = readw_relaxed(vaddr); ++ break; ++ case 32: ++ prev_val = readl_relaxed(vaddr); ++ break; ++ case 64: ++ prev_val = readq_relaxed(vaddr); ++ break; ++ default: ++ spin_unlock(&cpc_desc->rmw_lock); ++ return -EFAULT; ++ } ++ val = MASK_VAL_WRITE(reg, prev_val, val); ++ val |= prev_val; ++ } + + switch (size) { + case 8: +@@ -1134,6 +1166,9 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val) + break; + } + ++ if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) ++ spin_unlock(&cpc_desc->rmw_lock); ++ + return ret_val; + } + +diff --git a/drivers/acpi/device_sysfs.c b/drivers/acpi/device_sysfs.c +index 23373faa35ecd6..95a19e3569c83f 100644 +--- a/drivers/acpi/device_sysfs.c ++++ b/drivers/acpi/device_sysfs.c +@@ -540,8 +540,9 @@ int acpi_device_setup_files(struct acpi_device *dev) + * If device has _STR, 'description' file is created + */ + if (acpi_has_method(dev->handle, "_STR")) { +- status = acpi_evaluate_object(dev->handle, "_STR", +- NULL, &buffer); ++ status = acpi_evaluate_object_typed(dev->handle, "_STR", ++ NULL, &buffer, ++ ACPI_TYPE_BUFFER); + if (ACPI_FAILURE(status)) + buffer.pointer = NULL; + dev->pnp.str_obj = buffer.pointer; +diff --git a/drivers/acpi/pmic/tps68470_pmic.c b/drivers/acpi/pmic/tps68470_pmic.c +index ebd03e4729555a..0d1a82eeb4b0b6 100644 +--- a/drivers/acpi/pmic/tps68470_pmic.c ++++ b/drivers/acpi/pmic/tps68470_pmic.c +@@ -376,10 +376,8 @@ static int tps68470_pmic_opregion_probe(struct platform_device *pdev) + struct tps68470_pmic_opregion *opregion; + acpi_status status; + +- if (!dev || !tps68470_regmap) { +- dev_warn(dev, "dev or regmap is NULL\n"); +- return -EINVAL; +- } ++ if (!tps68470_regmap) ++ return dev_err_probe(dev, -EINVAL, "regmap is missing\n"); + + if (!handle) { + dev_warn(dev, "acpi handle is NULL\n"); +diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c +index df5d5a554b388b..cb2aacbb93357e 100644 +--- a/drivers/acpi/resource.c ++++ b/drivers/acpi/resource.c +@@ -554,6 +554,12 @@ static const struct dmi_system_id irq1_level_low_skip_override[] = { + * to have a working keyboard. + */ + static const struct dmi_system_id irq1_edge_low_force_override[] = { ++ { ++ /* MECHREV Jiaolong17KS Series GM7XG0M */ ++ .matches = { ++ DMI_MATCH(DMI_BOARD_NAME, "GM7XG0M"), ++ }, ++ }, + { + /* XMG APEX 17 (M23) */ + .matches = { +@@ -572,6 +578,12 @@ static const struct dmi_system_id irq1_edge_low_force_override[] = { + DMI_MATCH(DMI_BOARD_NAME, "GMxXGxx"), + }, + }, ++ { ++ /* TongFang GMxXGxX/TUXEDO Polaris 15 Gen5 AMD */ ++ .matches = { ++ DMI_MATCH(DMI_BOARD_NAME, "GMxXGxX"), ++ }, ++ }, + { + /* TongFang GMxXGxx sold as Eluktronics Inc. RP-15 */ + .matches = { +diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c +index ff6f260433a113..75a5f559402f87 100644 +--- a/drivers/acpi/video_detect.c ++++ b/drivers/acpi/video_detect.c +@@ -541,6 +541,22 @@ static const struct dmi_system_id video_detect_dmi_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "iMac12,2"), + }, + }, ++ { ++ .callback = video_detect_force_native, ++ /* Apple MacBook Air 9,1 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir9,1"), ++ }, ++ }, ++ { ++ .callback = video_detect_force_native, ++ /* Apple MacBook Pro 9,2 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro9,2"), ++ }, ++ }, + { + /* https://bugzilla.redhat.com/show_bug.cgi?id=1217249 */ + .callback = video_detect_force_native, +@@ -550,6 +566,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro12,1"), + }, + }, ++ { ++ .callback = video_detect_force_native, ++ /* Apple MacBook Pro 16,2 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro16,2"), ++ }, ++ }, + { + .callback = video_detect_force_native, + /* Dell Inspiron N4010 */ +diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c +index 214b935c2ced79..7df9ec9f924c44 100644 +--- a/drivers/ata/libata-eh.c ++++ b/drivers/ata/libata-eh.c +@@ -630,6 +630,14 @@ void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap, + list_for_each_entry_safe(scmd, tmp, eh_work_q, eh_entry) { + struct ata_queued_cmd *qc; + ++ /* ++ * If the scmd was added to EH, via ata_qc_schedule_eh() -> ++ * scsi_timeout() -> scsi_eh_scmd_add(), scsi_timeout() will ++ * have set DID_TIME_OUT (since libata does not have an abort ++ * handler). Thus, to clear DID_TIME_OUT, clear the host byte. ++ */ ++ set_host_byte(scmd, DID_OK); ++ + ata_qc_for_each_raw(ap, qc, i) { + if (qc->flags & ATA_QCFLAG_ACTIVE && + qc->scsicmd == scmd) +diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c +index 4116ae08871910..0cbe331124c255 100644 +--- a/drivers/ata/libata-scsi.c ++++ b/drivers/ata/libata-scsi.c +@@ -1693,9 +1693,6 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) + set_status_byte(qc->scsicmd, SAM_STAT_CHECK_CONDITION); + } else if (is_error && !have_sense) { + ata_gen_ata_sense(qc); +- } else { +- /* Keep the SCSI ML and status byte, clear host byte. */ +- cmd->result &= 0x0000ffff; + } + + ata_qc_done(qc); +@@ -2361,7 +2358,7 @@ static unsigned int ata_msense_control(struct ata_device *dev, u8 *buf, + case ALL_SUB_MPAGES: + n = ata_msense_control_spg0(dev, buf, changeable); + n += ata_msense_control_spgt2(dev, buf + n, CDL_T2A_SUB_MPAGE); +- n += ata_msense_control_spgt2(dev, buf + n, CDL_T2A_SUB_MPAGE); ++ n += ata_msense_control_spgt2(dev, buf + n, CDL_T2B_SUB_MPAGE); + n += ata_msense_control_ata_feature(dev, buf + n); + return n; + default: +diff --git a/drivers/base/core.c b/drivers/base/core.c +index b5399262198a68..6c1a944c00d9b3 100644 +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -4515,9 +4515,11 @@ EXPORT_SYMBOL_GPL(device_destroy); + */ + int device_rename(struct device *dev, const char *new_name) + { ++ struct subsys_private *sp = NULL; + struct kobject *kobj = &dev->kobj; + char *old_device_name = NULL; + int error; ++ bool is_link_renamed = false; + + dev = get_device(dev); + if (!dev) +@@ -4532,7 +4534,7 @@ int device_rename(struct device *dev, const char *new_name) + } + + if (dev->class) { +- struct subsys_private *sp = class_to_subsys(dev->class); ++ sp = class_to_subsys(dev->class); + + if (!sp) { + error = -EINVAL; +@@ -4541,16 +4543,19 @@ int device_rename(struct device *dev, const char *new_name) + + error = sysfs_rename_link_ns(&sp->subsys.kobj, kobj, old_device_name, + new_name, kobject_namespace(kobj)); +- subsys_put(sp); + if (error) + goto out; ++ ++ is_link_renamed = true; + } + + error = kobject_rename(kobj, new_name); +- if (error) +- goto out; +- + out: ++ if (error && is_link_renamed) ++ sysfs_rename_link_ns(&sp->subsys.kobj, kobj, new_name, ++ old_device_name, kobject_namespace(kobj)); ++ subsys_put(sp); ++ + put_device(dev); + + kfree(old_device_name); +diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c +index da8ca01d011c3f..0989a62962d33c 100644 +--- a/drivers/base/firmware_loader/main.c ++++ b/drivers/base/firmware_loader/main.c +@@ -849,6 +849,26 @@ static void fw_log_firmware_info(const struct firmware *fw, const char *name, + {} + #endif + ++/* ++ * Reject firmware file names with ".." path components. ++ * There are drivers that construct firmware file names from device-supplied ++ * strings, and we don't want some device to be able to tell us "I would like to ++ * be sent my firmware from ../../../etc/shadow, please". ++ * ++ * Search for ".." surrounded by either '/' or start/end of string. ++ * ++ * This intentionally only looks at the firmware name, not at the firmware base ++ * directory or at symlink contents. ++ */ ++static bool name_contains_dotdot(const char *name) ++{ ++ size_t name_len = strlen(name); ++ ++ return strcmp(name, "..") == 0 || strncmp(name, "../", 3) == 0 || ++ strstr(name, "/../") != NULL || ++ (name_len >= 3 && strcmp(name+name_len-3, "/..") == 0); ++} ++ + /* called from request_firmware() and request_firmware_work_func() */ + static int + _request_firmware(const struct firmware **firmware_p, const char *name, +@@ -869,6 +889,14 @@ _request_firmware(const struct firmware **firmware_p, const char *name, + goto out; + } + ++ if (name_contains_dotdot(name)) { ++ dev_warn(device, ++ "Firmware load for '%s' refused, path contains '..' component\n", ++ name); ++ ret = -EINVAL; ++ goto out; ++ } ++ + ret = _request_firmware_prepare(&fw, name, device, buf, size, + offset, opt_flags); + if (ret <= 0) /* error or already assigned */ +@@ -946,6 +974,8 @@ _request_firmware(const struct firmware **firmware_p, const char *name, + * @name will be used as $FIRMWARE in the uevent environment and + * should be distinctive enough not to be confused with any other + * firmware image for this or any other device. ++ * It must not contain any ".." path components - "foo/bar..bin" is ++ * allowed, but "foo/../bar.bin" is not. + * + * Caller must hold the reference count of @device. + * +diff --git a/drivers/base/module.c b/drivers/base/module.c +index b0b79b9c189d4f..0d5c5da367f720 100644 +--- a/drivers/base/module.c ++++ b/drivers/base/module.c +@@ -66,27 +66,31 @@ int module_add_driver(struct module *mod, struct device_driver *drv) + driver_name = make_driver_name(drv); + if (!driver_name) { + ret = -ENOMEM; +- goto out; ++ goto out_remove_kobj; + } + + module_create_drivers_dir(mk); + if (!mk->drivers_dir) { + ret = -EINVAL; +- goto out; ++ goto out_free_driver_name; + } + + ret = sysfs_create_link(mk->drivers_dir, &drv->p->kobj, driver_name); + if (ret) +- goto out; ++ goto out_remove_drivers_dir; + + kfree(driver_name); + + return 0; +-out: +- sysfs_remove_link(&drv->p->kobj, "module"); ++ ++out_remove_drivers_dir: + sysfs_remove_link(mk->drivers_dir, driver_name); ++ ++out_free_driver_name: + kfree(driver_name); + ++out_remove_kobj: ++ sysfs_remove_link(&drv->p->kobj, "module"); + return ret; + } + +diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c +index 113b441d4d3670..301843297fb788 100644 +--- a/drivers/block/drbd/drbd_main.c ++++ b/drivers/block/drbd/drbd_main.c +@@ -3399,10 +3399,12 @@ void drbd_uuid_new_current(struct drbd_device *device) __must_hold(local) + void drbd_uuid_set_bm(struct drbd_device *device, u64 val) __must_hold(local) + { + unsigned long flags; +- if (device->ldev->md.uuid[UI_BITMAP] == 0 && val == 0) ++ spin_lock_irqsave(&device->ldev->md.uuid_lock, flags); ++ if (device->ldev->md.uuid[UI_BITMAP] == 0 && val == 0) { ++ spin_unlock_irqrestore(&device->ldev->md.uuid_lock, flags); + return; ++ } + +- spin_lock_irqsave(&device->ldev->md.uuid_lock, flags); + if (val == 0) { + drbd_uuid_move_history(device); + device->ldev->md.uuid[UI_HISTORY_START] = device->ldev->md.uuid[UI_BITMAP]; +diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c +index e858e7e0383f26..c2b6c4d9729db9 100644 +--- a/drivers/block/drbd/drbd_state.c ++++ b/drivers/block/drbd/drbd_state.c +@@ -876,7 +876,7 @@ is_valid_state(struct drbd_device *device, union drbd_state ns) + ns.disk == D_OUTDATED) + rv = SS_CONNECTED_OUTDATES; + +- else if ((ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T) && ++ else if (nc && (ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T) && + (nc->verify_alg[0] == 0)) + rv = SS_NO_VERIFY_ALG; + +diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c +index b87aa80a46ddaa..d4e260d3218063 100644 +--- a/drivers/block/nbd.c ++++ b/drivers/block/nbd.c +@@ -181,6 +181,17 @@ static void nbd_requeue_cmd(struct nbd_cmd *cmd) + { + struct request *req = blk_mq_rq_from_pdu(cmd); + ++ lockdep_assert_held(&cmd->lock); ++ ++ /* ++ * Clear INFLIGHT flag so that this cmd won't be completed in ++ * normal completion path ++ * ++ * INFLIGHT flag will be set when the cmd is queued to nbd next ++ * time. ++ */ ++ __clear_bit(NBD_CMD_INFLIGHT, &cmd->flags); ++ + if (!test_and_set_bit(NBD_CMD_REQUEUED, &cmd->flags)) + blk_mq_requeue_request(req, true); + } +@@ -339,7 +350,7 @@ static int __nbd_set_size(struct nbd_device *nbd, loff_t bytesize, + + lim = queue_limits_start_update(nbd->disk->queue); + if (nbd->config->flags & NBD_FLAG_SEND_TRIM) +- lim.max_hw_discard_sectors = UINT_MAX; ++ lim.max_hw_discard_sectors = UINT_MAX >> SECTOR_SHIFT; + else + lim.max_hw_discard_sectors = 0; + lim.logical_block_size = blksize; +@@ -480,8 +491,8 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req) + nbd_mark_nsock_dead(nbd, nsock, 1); + mutex_unlock(&nsock->tx_lock); + } +- mutex_unlock(&cmd->lock); + nbd_requeue_cmd(cmd); ++ mutex_unlock(&cmd->lock); + nbd_config_put(nbd); + return BLK_EH_DONE; + } +diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c +index fc001e9f95f61a..d06c8ed29620b9 100644 +--- a/drivers/block/ublk_drv.c ++++ b/drivers/block/ublk_drv.c +@@ -71,9 +71,6 @@ struct ublk_rq_data { + struct llist_node node; + + struct kref ref; +- __u64 sector; +- __u32 operation; +- __u32 nr_zones; + }; + + struct ublk_uring_cmd_pdu { +@@ -214,6 +211,33 @@ static inline bool ublk_queue_is_zoned(struct ublk_queue *ubq) + + #ifdef CONFIG_BLK_DEV_ZONED + ++struct ublk_zoned_report_desc { ++ __u64 sector; ++ __u32 operation; ++ __u32 nr_zones; ++}; ++ ++static DEFINE_XARRAY(ublk_zoned_report_descs); ++ ++static int ublk_zoned_insert_report_desc(const struct request *req, ++ struct ublk_zoned_report_desc *desc) ++{ ++ return xa_insert(&ublk_zoned_report_descs, (unsigned long)req, ++ desc, GFP_KERNEL); ++} ++ ++static struct ublk_zoned_report_desc *ublk_zoned_erase_report_desc( ++ const struct request *req) ++{ ++ return xa_erase(&ublk_zoned_report_descs, (unsigned long)req); ++} ++ ++static struct ublk_zoned_report_desc *ublk_zoned_get_report_desc( ++ const struct request *req) ++{ ++ return xa_load(&ublk_zoned_report_descs, (unsigned long)req); ++} ++ + static int ublk_get_nr_zones(const struct ublk_device *ub) + { + const struct ublk_param_basic *p = &ub->params.basic; +@@ -310,7 +334,7 @@ static int ublk_report_zones(struct gendisk *disk, sector_t sector, + unsigned int zones_in_request = + min_t(unsigned int, remaining_zones, max_zones_per_request); + struct request *req; +- struct ublk_rq_data *pdu; ++ struct ublk_zoned_report_desc desc; + blk_status_t status; + + memset(buffer, 0, buffer_length); +@@ -321,20 +345,23 @@ static int ublk_report_zones(struct gendisk *disk, sector_t sector, + goto out; + } + +- pdu = blk_mq_rq_to_pdu(req); +- pdu->operation = UBLK_IO_OP_REPORT_ZONES; +- pdu->sector = sector; +- pdu->nr_zones = zones_in_request; ++ desc.operation = UBLK_IO_OP_REPORT_ZONES; ++ desc.sector = sector; ++ desc.nr_zones = zones_in_request; ++ ret = ublk_zoned_insert_report_desc(req, &desc); ++ if (ret) ++ goto free_req; + + ret = blk_rq_map_kern(disk->queue, req, buffer, buffer_length, + GFP_KERNEL); +- if (ret) { +- blk_mq_free_request(req); +- goto out; +- } ++ if (ret) ++ goto erase_desc; + + status = blk_execute_rq(req, 0); + ret = blk_status_to_errno(status); ++erase_desc: ++ ublk_zoned_erase_report_desc(req); ++free_req: + blk_mq_free_request(req); + if (ret) + goto out; +@@ -368,7 +395,7 @@ static blk_status_t ublk_setup_iod_zoned(struct ublk_queue *ubq, + { + struct ublksrv_io_desc *iod = ublk_get_iod(ubq, req->tag); + struct ublk_io *io = &ubq->ios[req->tag]; +- struct ublk_rq_data *pdu = blk_mq_rq_to_pdu(req); ++ struct ublk_zoned_report_desc *desc; + u32 ublk_op; + + switch (req_op(req)) { +@@ -391,12 +418,15 @@ static blk_status_t ublk_setup_iod_zoned(struct ublk_queue *ubq, + ublk_op = UBLK_IO_OP_ZONE_RESET_ALL; + break; + case REQ_OP_DRV_IN: +- ublk_op = pdu->operation; ++ desc = ublk_zoned_get_report_desc(req); ++ if (!desc) ++ return BLK_STS_IOERR; ++ ublk_op = desc->operation; + switch (ublk_op) { + case UBLK_IO_OP_REPORT_ZONES: + iod->op_flags = ublk_op | ublk_req_build_flags(req); +- iod->nr_zones = pdu->nr_zones; +- iod->start_sector = pdu->sector; ++ iod->nr_zones = desc->nr_zones; ++ iod->start_sector = desc->sector; + return BLK_STS_OK; + default: + return BLK_STS_IOERR; +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 0927f51867c26a..c41b86608ba866 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -1393,7 +1393,10 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags) + if (!urb) + return -ENOMEM; + +- size = le16_to_cpu(data->intr_ep->wMaxPacketSize); ++ /* Use maximum HCI Event size so the USB stack handles ++ * ZPL/short-transfer automatically. ++ */ ++ size = HCI_MAX_EVENT_SIZE; + + buf = kmalloc(size, mem_flags); + if (!buf) { +diff --git a/drivers/bus/arm-integrator-lm.c b/drivers/bus/arm-integrator-lm.c +index b715c8ab36e8bd..a65c79b08804f4 100644 +--- a/drivers/bus/arm-integrator-lm.c ++++ b/drivers/bus/arm-integrator-lm.c +@@ -85,6 +85,7 @@ static int integrator_ap_lm_probe(struct platform_device *pdev) + return -ENODEV; + } + map = syscon_node_to_regmap(syscon); ++ of_node_put(syscon); + if (IS_ERR(map)) { + dev_err(dev, + "could not find Integrator/AP system controller\n"); +diff --git a/drivers/bus/mhi/host/pci_generic.c b/drivers/bus/mhi/host/pci_generic.c +index 08844ee79654ae..edb54c97992877 100644 +--- a/drivers/bus/mhi/host/pci_generic.c ++++ b/drivers/bus/mhi/host/pci_generic.c +@@ -606,6 +606,15 @@ static const struct mhi_pci_dev_info mhi_telit_fn990_info = { + .mru_default = 32768, + }; + ++static const struct mhi_pci_dev_info mhi_telit_fe990a_info = { ++ .name = "telit-fe990a", ++ .config = &modem_telit_fn990_config, ++ .bar_num = MHI_PCI_DEFAULT_BAR_NUM, ++ .dma_data_width = 32, ++ .sideband_wake = false, ++ .mru_default = 32768, ++}; ++ + /* Keep the list sorted based on the PID. New VID should be added as the last entry */ + static const struct pci_device_id mhi_pci_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0304), +@@ -623,9 +632,9 @@ static const struct pci_device_id mhi_pci_id_table[] = { + /* Telit FN990 */ + { PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0308, 0x1c5d, 0x2010), + .driver_data = (kernel_ulong_t) &mhi_telit_fn990_info }, +- /* Telit FE990 */ ++ /* Telit FE990A */ + { PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0308, 0x1c5d, 0x2015), +- .driver_data = (kernel_ulong_t) &mhi_telit_fn990_info }, ++ .driver_data = (kernel_ulong_t) &mhi_telit_fe990a_info }, + { PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0308), + .driver_data = (kernel_ulong_t) &mhi_qcom_sdx65_info }, + { PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0309), +diff --git a/drivers/char/hw_random/bcm2835-rng.c b/drivers/char/hw_random/bcm2835-rng.c +index b03e8030062758..aa2b135e3ee230 100644 +--- a/drivers/char/hw_random/bcm2835-rng.c ++++ b/drivers/char/hw_random/bcm2835-rng.c +@@ -94,8 +94,10 @@ static int bcm2835_rng_init(struct hwrng *rng) + return ret; + + ret = reset_control_reset(priv->reset); +- if (ret) ++ if (ret) { ++ clk_disable_unprepare(priv->clk); + return ret; ++ } + + if (priv->mask_interrupts) { + /* mask the interrupt */ +diff --git a/drivers/char/hw_random/cctrng.c b/drivers/char/hw_random/cctrng.c +index c0d2f824769f88..4c50efc464835b 100644 +--- a/drivers/char/hw_random/cctrng.c ++++ b/drivers/char/hw_random/cctrng.c +@@ -622,6 +622,7 @@ static int __maybe_unused cctrng_resume(struct device *dev) + /* wait for Cryptocell reset completion */ + if (!cctrng_wait_for_reset_completion(drvdata)) { + dev_err(dev, "Cryptocell reset not completed"); ++ clk_disable_unprepare(drvdata->clk); + return -EBUSY; + } + +diff --git a/drivers/char/hw_random/mtk-rng.c b/drivers/char/hw_random/mtk-rng.c +index aa993753ab120b..1e3048f2bb38f0 100644 +--- a/drivers/char/hw_random/mtk-rng.c ++++ b/drivers/char/hw_random/mtk-rng.c +@@ -142,7 +142,7 @@ static int mtk_rng_probe(struct platform_device *pdev) + dev_set_drvdata(&pdev->dev, priv); + pm_runtime_set_autosuspend_delay(&pdev->dev, RNG_AUTOSUSPEND_TIMEOUT); + pm_runtime_use_autosuspend(&pdev->dev); +- pm_runtime_enable(&pdev->dev); ++ devm_pm_runtime_enable(&pdev->dev); + + dev_info(&pdev->dev, "registered RNG driver\n"); + +diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c +index 30b4c288c1bbc3..c3fbbf4d3db79a 100644 +--- a/drivers/char/tpm/tpm-dev-common.c ++++ b/drivers/char/tpm/tpm-dev-common.c +@@ -47,6 +47,8 @@ static ssize_t tpm_dev_transmit(struct tpm_chip *chip, struct tpm_space *space, + + if (!ret) + ret = tpm2_commit_space(chip, space, buf, &len); ++ else ++ tpm2_flush_space(chip); + + out_rc: + return ret ? ret : len; +diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c +index d3521aadd43eef..44f60730cff441 100644 +--- a/drivers/char/tpm/tpm2-sessions.c ++++ b/drivers/char/tpm/tpm2-sessions.c +@@ -1362,4 +1362,5 @@ int tpm2_sessions_init(struct tpm_chip *chip) + + return rc; + } ++EXPORT_SYMBOL(tpm2_sessions_init); + #endif /* CONFIG_TCG_TPM2_HMAC */ +diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c +index 4892d491da8dae..25a66870c165c5 100644 +--- a/drivers/char/tpm/tpm2-space.c ++++ b/drivers/char/tpm/tpm2-space.c +@@ -169,6 +169,9 @@ void tpm2_flush_space(struct tpm_chip *chip) + struct tpm_space *space = &chip->work_space; + int i; + ++ if (!space) ++ return; ++ + for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++) + if (space->context_tbl[i] && ~space->context_tbl[i]) + tpm2_flush_context(chip, space->context_tbl[i]); +diff --git a/drivers/clk/at91/sama7g5.c b/drivers/clk/at91/sama7g5.c +index 91b5c6f1481964..4e9594714b1428 100644 +--- a/drivers/clk/at91/sama7g5.c ++++ b/drivers/clk/at91/sama7g5.c +@@ -66,6 +66,7 @@ enum pll_component_id { + PLL_COMPID_FRAC, + PLL_COMPID_DIV0, + PLL_COMPID_DIV1, ++ PLL_COMPID_MAX, + }; + + /* +@@ -165,7 +166,7 @@ static struct sama7g5_pll { + u8 t; + u8 eid; + u8 safe_div; +-} sama7g5_plls[][PLL_ID_MAX] = { ++} sama7g5_plls[][PLL_COMPID_MAX] = { + [PLL_ID_CPU] = { + [PLL_COMPID_FRAC] = { + .n = "cpupll_fracck", +@@ -1038,7 +1039,7 @@ static void __init sama7g5_pmc_setup(struct device_node *np) + sama7g5_pmc->chws[PMC_MAIN] = hw; + + for (i = 0; i < PLL_ID_MAX; i++) { +- for (j = 0; j < 3; j++) { ++ for (j = 0; j < PLL_COMPID_MAX; j++) { + struct clk_hw *parent_hw; + + if (!sama7g5_plls[i][j].n) +diff --git a/drivers/clk/imx/clk-composite-7ulp.c b/drivers/clk/imx/clk-composite-7ulp.c +index e208ddc511339e..db7f40b07d1abf 100644 +--- a/drivers/clk/imx/clk-composite-7ulp.c ++++ b/drivers/clk/imx/clk-composite-7ulp.c +@@ -14,6 +14,7 @@ + #include "../clk-fractional-divider.h" + #include "clk.h" + ++#define PCG_PR_MASK BIT(31) + #define PCG_PCS_SHIFT 24 + #define PCG_PCS_MASK 0x7 + #define PCG_CGC_SHIFT 30 +@@ -78,6 +79,12 @@ static struct clk_hw *imx_ulp_clk_hw_composite(const char *name, + struct clk_hw *hw; + u32 val; + ++ val = readl(reg); ++ if (!(val & PCG_PR_MASK)) { ++ pr_info("PCC PR is 0 for clk:%s, bypass\n", name); ++ return 0; ++ } ++ + if (mux_present) { + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) +diff --git a/drivers/clk/imx/clk-composite-8m.c b/drivers/clk/imx/clk-composite-8m.c +index 8cc07d056a8384..f187582ba49196 100644 +--- a/drivers/clk/imx/clk-composite-8m.c ++++ b/drivers/clk/imx/clk-composite-8m.c +@@ -204,6 +204,34 @@ static const struct clk_ops imx8m_clk_composite_mux_ops = { + .determine_rate = imx8m_clk_composite_mux_determine_rate, + }; + ++static int imx8m_clk_composite_gate_enable(struct clk_hw *hw) ++{ ++ struct clk_gate *gate = to_clk_gate(hw); ++ unsigned long flags; ++ u32 val; ++ ++ spin_lock_irqsave(gate->lock, flags); ++ ++ val = readl(gate->reg); ++ val |= BIT(gate->bit_idx); ++ writel(val, gate->reg); ++ ++ spin_unlock_irqrestore(gate->lock, flags); ++ ++ return 0; ++} ++ ++static void imx8m_clk_composite_gate_disable(struct clk_hw *hw) ++{ ++ /* composite clk requires the disable hook */ ++} ++ ++static const struct clk_ops imx8m_clk_composite_gate_ops = { ++ .enable = imx8m_clk_composite_gate_enable, ++ .disable = imx8m_clk_composite_gate_disable, ++ .is_enabled = clk_gate_is_enabled, ++}; ++ + struct clk_hw *__imx8m_clk_hw_composite(const char *name, + const char * const *parent_names, + int num_parents, void __iomem *reg, +@@ -217,6 +245,7 @@ struct clk_hw *__imx8m_clk_hw_composite(const char *name, + struct clk_mux *mux; + const struct clk_ops *divider_ops; + const struct clk_ops *mux_ops; ++ const struct clk_ops *gate_ops; + + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) +@@ -257,20 +286,22 @@ struct clk_hw *__imx8m_clk_hw_composite(const char *name, + div->flags = CLK_DIVIDER_ROUND_CLOSEST; + + /* skip registering the gate ops if M4 is enabled */ +- if (!mcore_booted) { +- gate = kzalloc(sizeof(*gate), GFP_KERNEL); +- if (!gate) +- goto free_div; +- +- gate_hw = &gate->hw; +- gate->reg = reg; +- gate->bit_idx = PCG_CGC_SHIFT; +- gate->lock = &imx_ccm_lock; +- } ++ gate = kzalloc(sizeof(*gate), GFP_KERNEL); ++ if (!gate) ++ goto free_div; ++ ++ gate_hw = &gate->hw; ++ gate->reg = reg; ++ gate->bit_idx = PCG_CGC_SHIFT; ++ gate->lock = &imx_ccm_lock; ++ if (!mcore_booted) ++ gate_ops = &clk_gate_ops; ++ else ++ gate_ops = &imx8m_clk_composite_gate_ops; + + hw = clk_hw_register_composite(NULL, name, parent_names, num_parents, + mux_hw, mux_ops, div_hw, +- divider_ops, gate_hw, &clk_gate_ops, flags); ++ divider_ops, gate_hw, gate_ops, flags); + if (IS_ERR(hw)) + goto free_gate; + +diff --git a/drivers/clk/imx/clk-composite-93.c b/drivers/clk/imx/clk-composite-93.c +index 81164bdcd6cc9a..6c6c5a30f3282d 100644 +--- a/drivers/clk/imx/clk-composite-93.c ++++ b/drivers/clk/imx/clk-composite-93.c +@@ -76,6 +76,13 @@ static int imx93_clk_composite_gate_enable(struct clk_hw *hw) + + static void imx93_clk_composite_gate_disable(struct clk_hw *hw) + { ++ /* ++ * Skip disable the root clock gate if mcore enabled. ++ * The root clock may be used by the mcore. ++ */ ++ if (mcore_booted) ++ return; ++ + imx93_clk_composite_gate_endisable(hw, 0); + } + +@@ -222,7 +229,7 @@ struct clk_hw *imx93_clk_composite_flags(const char *name, const char * const *p + hw = clk_hw_register_composite(NULL, name, parent_names, num_parents, + mux_hw, &clk_mux_ro_ops, div_hw, + &clk_divider_ro_ops, NULL, NULL, flags); +- } else if (!mcore_booted) { ++ } else { + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) + goto fail; +@@ -238,12 +245,6 @@ struct clk_hw *imx93_clk_composite_flags(const char *name, const char * const *p + &imx93_clk_composite_divider_ops, gate_hw, + &imx93_clk_composite_gate_ops, + flags | CLK_SET_RATE_NO_REPARENT); +- } else { +- hw = clk_hw_register_composite(NULL, name, parent_names, num_parents, +- mux_hw, &imx93_clk_composite_mux_ops, div_hw, +- &imx93_clk_composite_divider_ops, NULL, +- &imx93_clk_composite_gate_ops, +- flags | CLK_SET_RATE_NO_REPARENT); + } + + if (IS_ERR(hw)) +diff --git a/drivers/clk/imx/clk-fracn-gppll.c b/drivers/clk/imx/clk-fracn-gppll.c +index 44462ab50e513c..1becba2b62d0be 100644 +--- a/drivers/clk/imx/clk-fracn-gppll.c ++++ b/drivers/clk/imx/clk-fracn-gppll.c +@@ -291,6 +291,10 @@ static int clk_fracn_gppll_prepare(struct clk_hw *hw) + if (val & POWERUP_MASK) + return 0; + ++ if (pll->flags & CLK_FRACN_GPPLL_FRACN) ++ writel_relaxed(readl_relaxed(pll->base + PLL_NUMERATOR), ++ pll->base + PLL_NUMERATOR); ++ + val |= CLKMUX_BYPASS; + writel_relaxed(val, pll->base + PLL_CTRL); + +diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c +index f9394e94f69d73..05c7a82b751f3c 100644 +--- a/drivers/clk/imx/clk-imx6ul.c ++++ b/drivers/clk/imx/clk-imx6ul.c +@@ -542,8 +542,8 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node) + + clk_set_parent(hws[IMX6UL_CLK_ENFC_SEL]->clk, hws[IMX6UL_CLK_PLL2_PFD2]->clk); + +- clk_set_parent(hws[IMX6UL_CLK_ENET1_REF_SEL]->clk, hws[IMX6UL_CLK_ENET_REF]->clk); +- clk_set_parent(hws[IMX6UL_CLK_ENET2_REF_SEL]->clk, hws[IMX6UL_CLK_ENET2_REF]->clk); ++ clk_set_parent(hws[IMX6UL_CLK_ENET1_REF_SEL]->clk, hws[IMX6UL_CLK_ENET1_REF_125M]->clk); ++ clk_set_parent(hws[IMX6UL_CLK_ENET2_REF_SEL]->clk, hws[IMX6UL_CLK_ENET2_REF_125M]->clk); + + imx_register_uart_clocks(); + } +diff --git a/drivers/clk/imx/clk-imx8mp-audiomix.c b/drivers/clk/imx/clk-imx8mp-audiomix.c +index b381d6f784c890..0767d613b68b00 100644 +--- a/drivers/clk/imx/clk-imx8mp-audiomix.c ++++ b/drivers/clk/imx/clk-imx8mp-audiomix.c +@@ -154,6 +154,15 @@ static const struct clk_parent_data clk_imx8mp_audiomix_pll_bypass_sels[] = { + PDM_SEL, 2, 0 \ + } + ++#define CLK_GATE_PARENT(gname, cname, pname) \ ++ { \ ++ gname"_cg", \ ++ IMX8MP_CLK_AUDIOMIX_##cname, \ ++ { .fw_name = pname, .name = pname }, NULL, 1, \ ++ CLKEN0 + 4 * !!(IMX8MP_CLK_AUDIOMIX_##cname / 32), \ ++ 1, IMX8MP_CLK_AUDIOMIX_##cname % 32 \ ++ } ++ + struct clk_imx8mp_audiomix_sel { + const char *name; + int clkid; +@@ -171,14 +180,14 @@ static struct clk_imx8mp_audiomix_sel sels[] = { + CLK_GATE("earc", EARC_IPG), + CLK_GATE("ocrama", OCRAMA_IPG), + CLK_GATE("aud2htx", AUD2HTX_IPG), +- CLK_GATE("earc_phy", EARC_PHY), ++ CLK_GATE_PARENT("earc_phy", EARC_PHY, "sai_pll_out_div2"), + CLK_GATE("sdma2", SDMA2_ROOT), + CLK_GATE("sdma3", SDMA3_ROOT), + CLK_GATE("spba2", SPBA2_ROOT), + CLK_GATE("dsp", DSP_ROOT), + CLK_GATE("dspdbg", DSPDBG_ROOT), + CLK_GATE("edma", EDMA_ROOT), +- CLK_GATE("audpll", AUDPLL_ROOT), ++ CLK_GATE_PARENT("audpll", AUDPLL_ROOT, "osc_24m"), + CLK_GATE("mu2", MU2_ROOT), + CLK_GATE("mu3", MU3_ROOT), + CLK_PDM, +diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c +index 670aa2bab3017e..e561ff7b135fb5 100644 +--- a/drivers/clk/imx/clk-imx8mp.c ++++ b/drivers/clk/imx/clk-imx8mp.c +@@ -551,8 +551,8 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) + + hws[IMX8MP_CLK_IPG_ROOT] = imx_clk_hw_divider2("ipg_root", "ahb_root", ccm_base + 0x9080, 0, 1); + +- hws[IMX8MP_CLK_DRAM_ALT] = imx8m_clk_hw_composite("dram_alt", imx8mp_dram_alt_sels, ccm_base + 0xa000); +- hws[IMX8MP_CLK_DRAM_APB] = imx8m_clk_hw_composite_critical("dram_apb", imx8mp_dram_apb_sels, ccm_base + 0xa080); ++ hws[IMX8MP_CLK_DRAM_ALT] = imx8m_clk_hw_fw_managed_composite("dram_alt", imx8mp_dram_alt_sels, ccm_base + 0xa000); ++ hws[IMX8MP_CLK_DRAM_APB] = imx8m_clk_hw_fw_managed_composite_critical("dram_apb", imx8mp_dram_apb_sels, ccm_base + 0xa080); + hws[IMX8MP_CLK_VPU_G1] = imx8m_clk_hw_composite("vpu_g1", imx8mp_vpu_g1_sels, ccm_base + 0xa100); + hws[IMX8MP_CLK_VPU_G2] = imx8m_clk_hw_composite("vpu_g2", imx8mp_vpu_g2_sels, ccm_base + 0xa180); + hws[IMX8MP_CLK_CAN1] = imx8m_clk_hw_composite("can1", imx8mp_can1_sels, ccm_base + 0xa200); +diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c +index 7d8883916cacdd..83f2e8bd6d5062 100644 +--- a/drivers/clk/imx/clk-imx8qxp.c ++++ b/drivers/clk/imx/clk-imx8qxp.c +@@ -170,8 +170,8 @@ static int imx8qxp_clk_probe(struct platform_device *pdev) + imx_clk_scu("pwm_clk", IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("elcdif_pll", IMX_SC_R_ELCDIF_PLL, IMX_SC_PM_CLK_PLL); + imx_clk_scu2("lcd_clk", lcd_sels, ARRAY_SIZE(lcd_sels), IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER); +- imx_clk_scu2("lcd_pxl_clk", lcd_pxl_sels, ARRAY_SIZE(lcd_pxl_sels), IMX_SC_R_LCD_0, IMX_SC_PM_CLK_MISC0); + imx_clk_scu("lcd_pxl_bypass_div_clk", IMX_SC_R_LCD_0, IMX_SC_PM_CLK_BYPASS); ++ imx_clk_scu2("lcd_pxl_clk", lcd_pxl_sels, ARRAY_SIZE(lcd_pxl_sels), IMX_SC_R_LCD_0, IMX_SC_PM_CLK_MISC0); + + /* Audio SS */ + imx_clk_scu("audio_pll0_clk", IMX_SC_R_AUDIO_PLL_0, IMX_SC_PM_CLK_PLL); +@@ -206,18 +206,18 @@ static int imx8qxp_clk_probe(struct platform_device *pdev) + imx_clk_scu("usb3_lpm_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MISC); + + /* Display controller SS */ +- imx_clk_scu2("dc0_disp0_clk", dc0_sels, ARRAY_SIZE(dc0_sels), IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC0); +- imx_clk_scu2("dc0_disp1_clk", dc0_sels, ARRAY_SIZE(dc0_sels), IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC1); + imx_clk_scu("dc0_pll0_clk", IMX_SC_R_DC_0_PLL_0, IMX_SC_PM_CLK_PLL); + imx_clk_scu("dc0_pll1_clk", IMX_SC_R_DC_0_PLL_1, IMX_SC_PM_CLK_PLL); + imx_clk_scu("dc0_bypass0_clk", IMX_SC_R_DC_0_VIDEO0, IMX_SC_PM_CLK_BYPASS); ++ imx_clk_scu2("dc0_disp0_clk", dc0_sels, ARRAY_SIZE(dc0_sels), IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC0); ++ imx_clk_scu2("dc0_disp1_clk", dc0_sels, ARRAY_SIZE(dc0_sels), IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC1); + imx_clk_scu("dc0_bypass1_clk", IMX_SC_R_DC_0_VIDEO1, IMX_SC_PM_CLK_BYPASS); + +- imx_clk_scu2("dc1_disp0_clk", dc1_sels, ARRAY_SIZE(dc1_sels), IMX_SC_R_DC_1, IMX_SC_PM_CLK_MISC0); +- imx_clk_scu2("dc1_disp1_clk", dc1_sels, ARRAY_SIZE(dc1_sels), IMX_SC_R_DC_1, IMX_SC_PM_CLK_MISC1); + imx_clk_scu("dc1_pll0_clk", IMX_SC_R_DC_1_PLL_0, IMX_SC_PM_CLK_PLL); + imx_clk_scu("dc1_pll1_clk", IMX_SC_R_DC_1_PLL_1, IMX_SC_PM_CLK_PLL); + imx_clk_scu("dc1_bypass0_clk", IMX_SC_R_DC_1_VIDEO0, IMX_SC_PM_CLK_BYPASS); ++ imx_clk_scu2("dc1_disp0_clk", dc1_sels, ARRAY_SIZE(dc1_sels), IMX_SC_R_DC_1, IMX_SC_PM_CLK_MISC0); ++ imx_clk_scu2("dc1_disp1_clk", dc1_sels, ARRAY_SIZE(dc1_sels), IMX_SC_R_DC_1, IMX_SC_PM_CLK_MISC1); + imx_clk_scu("dc1_bypass1_clk", IMX_SC_R_DC_1_VIDEO1, IMX_SC_PM_CLK_BYPASS); + + /* MIPI-LVDS SS */ +diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c +index 25a7b4b15c56ab..2720cbc40e0acc 100644 +--- a/drivers/clk/qcom/clk-alpha-pll.c ++++ b/drivers/clk/qcom/clk-alpha-pll.c +@@ -1784,6 +1784,58 @@ const struct clk_ops clk_alpha_pll_agera_ops = { + }; + EXPORT_SYMBOL_GPL(clk_alpha_pll_agera_ops); + ++/** ++ * clk_lucid_5lpe_pll_configure - configure the lucid 5lpe pll ++ * ++ * @pll: clk alpha pll ++ * @regmap: register map ++ * @config: configuration to apply for pll ++ */ ++void clk_lucid_5lpe_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, ++ const struct alpha_pll_config *config) ++{ ++ /* ++ * If the bootloader left the PLL enabled it's likely that there are ++ * RCGs that will lock up if we disable the PLL below. ++ */ ++ if (trion_pll_is_enabled(pll, regmap)) { ++ pr_debug("Lucid 5LPE PLL is already enabled, skipping configuration\n"); ++ return; ++ } ++ ++ clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l); ++ regmap_write(regmap, PLL_CAL_L_VAL(pll), TRION_PLL_CAL_VAL); ++ clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha); ++ clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll), ++ config->config_ctl_val); ++ clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll), ++ config->config_ctl_hi_val); ++ clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U1(pll), ++ config->config_ctl_hi1_val); ++ clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll), ++ config->user_ctl_val); ++ clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll), ++ config->user_ctl_hi_val); ++ clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U1(pll), ++ config->user_ctl_hi1_val); ++ clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), ++ config->test_ctl_val); ++ clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), ++ config->test_ctl_hi_val); ++ clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U1(pll), ++ config->test_ctl_hi1_val); ++ ++ /* Disable PLL output */ ++ regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); ++ ++ /* Set operation mode to OFF */ ++ regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY); ++ ++ /* Place the PLL in STANDBY mode */ ++ regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); ++} ++EXPORT_SYMBOL_GPL(clk_lucid_5lpe_pll_configure); ++ + static int alpha_pll_lucid_5lpe_enable(struct clk_hw *hw) + { + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); +diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h +index c7055b6c42f1d5..d89ec4723e2d9c 100644 +--- a/drivers/clk/qcom/clk-alpha-pll.h ++++ b/drivers/clk/qcom/clk-alpha-pll.h +@@ -205,6 +205,8 @@ void clk_agera_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, + + void clk_zonda_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, + const struct alpha_pll_config *config); ++void clk_lucid_5lpe_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, ++ const struct alpha_pll_config *config); + void clk_lucid_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, + const struct alpha_pll_config *config); + void clk_lucid_ole_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, +diff --git a/drivers/clk/qcom/dispcc-sm8250.c b/drivers/clk/qcom/dispcc-sm8250.c +index 43307c8a342cae..2103e22ca3ddee 100644 +--- a/drivers/clk/qcom/dispcc-sm8250.c ++++ b/drivers/clk/qcom/dispcc-sm8250.c +@@ -1357,8 +1357,13 @@ static int disp_cc_sm8250_probe(struct platform_device *pdev) + disp_cc_sm8250_clocks[DISP_CC_MDSS_EDP_GTC_CLK_SRC] = NULL; + } + +- clk_lucid_pll_configure(&disp_cc_pll0, regmap, &disp_cc_pll0_config); +- clk_lucid_pll_configure(&disp_cc_pll1, regmap, &disp_cc_pll1_config); ++ if (of_device_is_compatible(pdev->dev.of_node, "qcom,sm8350-dispcc")) { ++ clk_lucid_5lpe_pll_configure(&disp_cc_pll0, regmap, &disp_cc_pll0_config); ++ clk_lucid_5lpe_pll_configure(&disp_cc_pll1, regmap, &disp_cc_pll1_config); ++ } else { ++ clk_lucid_pll_configure(&disp_cc_pll0, regmap, &disp_cc_pll0_config); ++ clk_lucid_pll_configure(&disp_cc_pll1, regmap, &disp_cc_pll1_config); ++ } + + /* Enable clock gating for MDP clocks */ + regmap_update_bits(regmap, 0x8000, 0x10, 0x10); +diff --git a/drivers/clk/qcom/dispcc-sm8550.c b/drivers/clk/qcom/dispcc-sm8550.c +index 38ecea805503d3..1ba01bdb763b7f 100644 +--- a/drivers/clk/qcom/dispcc-sm8550.c ++++ b/drivers/clk/qcom/dispcc-sm8550.c +@@ -196,7 +196,7 @@ static const struct clk_parent_data disp_cc_parent_data_3[] = { + static const struct parent_map disp_cc_parent_map_4[] = { + { P_BI_TCXO, 0 }, + { P_DP0_PHY_PLL_LINK_CLK, 1 }, +- { P_DP1_PHY_PLL_VCO_DIV_CLK, 2 }, ++ { P_DP0_PHY_PLL_VCO_DIV_CLK, 2 }, + { P_DP3_PHY_PLL_VCO_DIV_CLK, 3 }, + { P_DP1_PHY_PLL_VCO_DIV_CLK, 4 }, + { P_DP2_PHY_PLL_VCO_DIV_CLK, 6 }, +@@ -213,7 +213,7 @@ static const struct clk_parent_data disp_cc_parent_data_4[] = { + + static const struct parent_map disp_cc_parent_map_5[] = { + { P_BI_TCXO, 0 }, +- { P_DSI0_PHY_PLL_OUT_BYTECLK, 4 }, ++ { P_DSI0_PHY_PLL_OUT_BYTECLK, 2 }, + { P_DSI1_PHY_PLL_OUT_BYTECLK, 4 }, + }; + +@@ -400,7 +400,7 @@ static struct clk_rcg2 disp_cc_mdss_dptx1_aux_clk_src = { + .parent_data = disp_cc_parent_data_0, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_dp_ops, ++ .ops = &clk_rcg2_ops, + }, + }; + +@@ -562,7 +562,7 @@ static struct clk_rcg2 disp_cc_mdss_esc0_clk_src = { + .parent_data = disp_cc_parent_data_5, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_5), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -577,7 +577,7 @@ static struct clk_rcg2 disp_cc_mdss_esc1_clk_src = { + .parent_data = disp_cc_parent_data_5, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_5), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -1611,7 +1611,7 @@ static struct gdsc mdss_gdsc = { + .name = "mdss_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +- .flags = HW_CTRL | RETAIN_FF_ENABLE, ++ .flags = POLL_CFG_GDSCR | HW_CTRL | RETAIN_FF_ENABLE, + }; + + static struct gdsc mdss_int2_gdsc = { +@@ -1620,7 +1620,7 @@ static struct gdsc mdss_int2_gdsc = { + .name = "mdss_int2_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +- .flags = HW_CTRL | RETAIN_FF_ENABLE, ++ .flags = POLL_CFG_GDSCR | HW_CTRL | RETAIN_FF_ENABLE, + }; + + static struct clk_regmap *disp_cc_sm8550_clocks[] = { +diff --git a/drivers/clk/qcom/gcc-ipq5332.c b/drivers/clk/qcom/gcc-ipq5332.c +index f98591148a9767..6a4877d8882946 100644 +--- a/drivers/clk/qcom/gcc-ipq5332.c ++++ b/drivers/clk/qcom/gcc-ipq5332.c +@@ -3388,6 +3388,7 @@ static struct clk_regmap *gcc_ipq5332_clocks[] = { + [GCC_QDSS_DAP_DIV_CLK_SRC] = &gcc_qdss_dap_div_clk_src.clkr, + [GCC_QDSS_ETR_USB_CLK] = &gcc_qdss_etr_usb_clk.clkr, + [GCC_QDSS_EUD_AT_CLK] = &gcc_qdss_eud_at_clk.clkr, ++ [GCC_QDSS_TSCTR_CLK_SRC] = &gcc_qdss_tsctr_clk_src.clkr, + [GCC_QPIC_AHB_CLK] = &gcc_qpic_ahb_clk.clkr, + [GCC_QPIC_CLK] = &gcc_qpic_clk.clkr, + [GCC_QPIC_IO_MACRO_CLK] = &gcc_qpic_io_macro_clk.clkr, +diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c +index a24a35553e1349..7343d2d7676bca 100644 +--- a/drivers/clk/rockchip/clk-rk3228.c ++++ b/drivers/clk/rockchip/clk-rk3228.c +@@ -409,7 +409,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + RK2928_CLKSEL_CON(29), 0, 3, DFLAGS), + DIV(0, "sclk_vop_pre", "sclk_vop_src", 0, + RK2928_CLKSEL_CON(27), 8, 8, DFLAGS), +- MUX(DCLK_VOP, "dclk_vop", mux_dclk_vop_p, 0, ++ MUX(DCLK_VOP, "dclk_vop", mux_dclk_vop_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + RK2928_CLKSEL_CON(27), 1, 1, MFLAGS), + + FACTOR(0, "xin12m", "xin24m", 0, 1, 2), +diff --git a/drivers/clk/rockchip/clk-rk3588.c b/drivers/clk/rockchip/clk-rk3588.c +index b30279a96dc8af..3027379f2fdd11 100644 +--- a/drivers/clk/rockchip/clk-rk3588.c ++++ b/drivers/clk/rockchip/clk-rk3588.c +@@ -526,7 +526,7 @@ PNAME(pmu_200m_100m_p) = { "clk_pmu1_200m_src", "clk_pmu1_100m_src" }; + PNAME(pmu_300m_24m_p) = { "clk_300m_src", "xin24m" }; + PNAME(pmu_400m_24m_p) = { "clk_400m_src", "xin24m" }; + PNAME(pmu_100m_50m_24m_src_p) = { "clk_pmu1_100m_src", "clk_pmu1_50m_src", "xin24m" }; +-PNAME(pmu_24m_32k_100m_src_p) = { "xin24m", "32k", "clk_pmu1_100m_src" }; ++PNAME(pmu_24m_32k_100m_src_p) = { "xin24m", "xin32k", "clk_pmu1_100m_src" }; + PNAME(hclk_pmu1_root_p) = { "clk_pmu1_200m_src", "clk_pmu1_100m_src", "clk_pmu1_50m_src", "xin24m" }; + PNAME(hclk_pmu_cm0_root_p) = { "clk_pmu1_400m_src", "clk_pmu1_200m_src", "clk_pmu1_100m_src", "xin24m" }; + PNAME(mclk_pdm0_p) = { "clk_pmu1_300m_src", "clk_pmu1_200m_src" }; +diff --git a/drivers/clk/starfive/clk-starfive-jh7110-vout.c b/drivers/clk/starfive/clk-starfive-jh7110-vout.c +index 53f7af234cc23e..aabd0484ac23f6 100644 +--- a/drivers/clk/starfive/clk-starfive-jh7110-vout.c ++++ b/drivers/clk/starfive/clk-starfive-jh7110-vout.c +@@ -145,7 +145,7 @@ static int jh7110_voutcrg_probe(struct platform_device *pdev) + + /* enable power domain and clocks */ + pm_runtime_enable(priv->dev); +- ret = pm_runtime_get_sync(priv->dev); ++ ret = pm_runtime_resume_and_get(priv->dev); + if (ret < 0) + return dev_err_probe(priv->dev, ret, "failed to turn on power\n"); + +diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c +index d964e3affd42ce..0eab7f3e2eab9e 100644 +--- a/drivers/clk/ti/clk-dra7-atl.c ++++ b/drivers/clk/ti/clk-dra7-atl.c +@@ -240,6 +240,7 @@ static int of_dra7_atl_clk_probe(struct platform_device *pdev) + } + + clk = of_clk_get_from_provider(&clkspec); ++ of_node_put(clkspec.np); + if (IS_ERR(clk)) { + pr_err("%s: failed to get atl clock %d from provider\n", + __func__, i); +diff --git a/drivers/clocksource/timer-qcom.c b/drivers/clocksource/timer-qcom.c +index b4afe3a6758351..eac4c95c6127f2 100644 +--- a/drivers/clocksource/timer-qcom.c ++++ b/drivers/clocksource/timer-qcom.c +@@ -233,6 +233,7 @@ static int __init msm_dt_timer_init(struct device_node *np) + } + + if (of_property_read_u32(np, "clock-frequency", &freq)) { ++ iounmap(cpu0_base); + pr_err("Unknown frequency\n"); + return -EINVAL; + } +@@ -243,7 +244,11 @@ static int __init msm_dt_timer_init(struct device_node *np) + freq /= 4; + writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL); + +- return msm_timer_init(freq, 32, irq, !!percpu_offset); ++ ret = msm_timer_init(freq, 32, irq, !!percpu_offset); ++ if (ret) ++ iounmap(cpu0_base); ++ ++ return ret; + } + TIMER_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init); + TIMER_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init); +diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c +index 5af85c4cbad0cc..f8e6dc3c14d359 100644 +--- a/drivers/cpufreq/ti-cpufreq.c ++++ b/drivers/cpufreq/ti-cpufreq.c +@@ -61,6 +61,9 @@ struct ti_cpufreq_soc_data { + unsigned long efuse_shift; + unsigned long rev_offset; + bool multi_regulator; ++/* Backward compatibility hack: Might have missing syscon */ ++#define TI_QUIRK_SYSCON_MAY_BE_MISSING 0x1 ++ u8 quirks; + }; + + struct ti_cpufreq_data { +@@ -182,6 +185,7 @@ static struct ti_cpufreq_soc_data omap34xx_soc_data = { + .efuse_mask = BIT(3), + .rev_offset = OMAP3_CONTROL_IDCODE - OMAP3_SYSCON_BASE, + .multi_regulator = false, ++ .quirks = TI_QUIRK_SYSCON_MAY_BE_MISSING, + }; + + /* +@@ -209,6 +213,7 @@ static struct ti_cpufreq_soc_data omap36xx_soc_data = { + .efuse_mask = BIT(9), + .rev_offset = OMAP3_CONTROL_IDCODE - OMAP3_SYSCON_BASE, + .multi_regulator = true, ++ .quirks = TI_QUIRK_SYSCON_MAY_BE_MISSING, + }; + + /* +@@ -223,6 +228,7 @@ static struct ti_cpufreq_soc_data am3517_soc_data = { + .efuse_mask = 0, + .rev_offset = OMAP3_CONTROL_IDCODE - OMAP3_SYSCON_BASE, + .multi_regulator = false, ++ .quirks = TI_QUIRK_SYSCON_MAY_BE_MISSING, + }; + + static struct ti_cpufreq_soc_data am625_soc_data = { +@@ -250,7 +256,7 @@ static int ti_cpufreq_get_efuse(struct ti_cpufreq_data *opp_data, + + ret = regmap_read(opp_data->syscon, opp_data->soc_data->efuse_offset, + &efuse); +- if (ret == -EIO) { ++ if (opp_data->soc_data->quirks & TI_QUIRK_SYSCON_MAY_BE_MISSING && ret == -EIO) { + /* not a syscon register! */ + void __iomem *regs = ioremap(OMAP3_SYSCON_BASE + + opp_data->soc_data->efuse_offset, 4); +@@ -291,7 +297,7 @@ static int ti_cpufreq_get_rev(struct ti_cpufreq_data *opp_data, + + ret = regmap_read(opp_data->syscon, opp_data->soc_data->rev_offset, + &revision); +- if (ret == -EIO) { ++ if (opp_data->soc_data->quirks & TI_QUIRK_SYSCON_MAY_BE_MISSING && ret == -EIO) { + /* not a syscon register! */ + void __iomem *regs = ioremap(OMAP3_SYSCON_BASE + + opp_data->soc_data->rev_offset, 4); +diff --git a/drivers/cpuidle/cpuidle-riscv-sbi.c b/drivers/cpuidle/cpuidle-riscv-sbi.c +index a6e123dfe394d8..5bb3401220d296 100644 +--- a/drivers/cpuidle/cpuidle-riscv-sbi.c ++++ b/drivers/cpuidle/cpuidle-riscv-sbi.c +@@ -8,6 +8,7 @@ + + #define pr_fmt(fmt) "cpuidle-riscv-sbi: " fmt + ++#include <linux/cleanup.h> + #include <linux/cpuhotplug.h> + #include <linux/cpuidle.h> + #include <linux/cpumask.h> +@@ -236,19 +237,16 @@ static int sbi_cpuidle_dt_init_states(struct device *dev, + { + struct sbi_cpuidle_data *data = per_cpu_ptr(&sbi_cpuidle_data, cpu); + struct device_node *state_node; +- struct device_node *cpu_node; + u32 *states; + int i, ret; + +- cpu_node = of_cpu_device_node_get(cpu); ++ struct device_node *cpu_node __free(device_node) = of_cpu_device_node_get(cpu); + if (!cpu_node) + return -ENODEV; + + states = devm_kcalloc(dev, state_count, sizeof(*states), GFP_KERNEL); +- if (!states) { +- ret = -ENOMEM; +- goto fail; +- } ++ if (!states) ++ return -ENOMEM; + + /* Parse SBI specific details from state DT nodes */ + for (i = 1; i < state_count; i++) { +@@ -264,10 +262,8 @@ static int sbi_cpuidle_dt_init_states(struct device *dev, + + pr_debug("sbi-state %#x index %d\n", states[i], i); + } +- if (i != state_count) { +- ret = -ENODEV; +- goto fail; +- } ++ if (i != state_count) ++ return -ENODEV; + + /* Initialize optional data, used for the hierarchical topology. */ + ret = sbi_dt_cpu_init_topology(drv, data, state_count, cpu); +@@ -277,10 +273,7 @@ static int sbi_cpuidle_dt_init_states(struct device *dev, + /* Store states in the per-cpu struct. */ + data->states = states; + +-fail: +- of_node_put(cpu_node); +- +- return ret; ++ return 0; + } + + static void sbi_cpuidle_deinit_cpu(int cpu) +diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c +index fdd724228c2fa8..25c02e26725858 100644 +--- a/drivers/crypto/caam/caamhash.c ++++ b/drivers/crypto/caam/caamhash.c +@@ -708,6 +708,7 @@ static struct ahash_edesc *ahash_edesc_alloc(struct ahash_request *req, + GFP_KERNEL : GFP_ATOMIC; + struct ahash_edesc *edesc; + ++ sg_num = pad_sg_nents(sg_num); + edesc = kzalloc(struct_size(edesc, sec4_sg, sg_num), flags); + if (!edesc) + return NULL; +diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c +index 1912bee22dd4a6..7407c9a1e844ed 100644 +--- a/drivers/crypto/ccp/sev-dev.c ++++ b/drivers/crypto/ccp/sev-dev.c +@@ -910,7 +910,18 @@ static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret) + + sev->int_rcvd = 0; + +- reg = FIELD_PREP(SEV_CMDRESP_CMD, cmd) | SEV_CMDRESP_IOC; ++ reg = FIELD_PREP(SEV_CMDRESP_CMD, cmd); ++ ++ /* ++ * If invoked during panic handling, local interrupts are disabled so ++ * the PSP command completion interrupt can't be used. ++ * sev_wait_cmd_ioc() already checks for interrupts disabled and ++ * polls for PSP command completion. Ensure we do not request an ++ * interrupt from the PSP if irqs disabled. ++ */ ++ if (!irqs_disabled()) ++ reg |= SEV_CMDRESP_IOC; ++ + iowrite32(reg, sev->io_regs + sev->vdata->cmdresp_reg); + + /* wait for command completion */ +@@ -2374,6 +2385,8 @@ void sev_pci_init(void) + return; + + err: ++ sev_dev_destroy(psp_master); ++ + psp_master->sev_data = NULL; + } + +diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c +index 10aa4da93323f1..6b536ad2ada52a 100644 +--- a/drivers/crypto/hisilicon/hpre/hpre_main.c ++++ b/drivers/crypto/hisilicon/hpre/hpre_main.c +@@ -13,9 +13,7 @@ + #include <linux/uacce.h> + #include "hpre.h" + +-#define HPRE_QM_ABNML_INT_MASK 0x100004 + #define HPRE_CTRL_CNT_CLR_CE_BIT BIT(0) +-#define HPRE_COMM_CNT_CLR_CE 0x0 + #define HPRE_CTRL_CNT_CLR_CE 0x301000 + #define HPRE_FSM_MAX_CNT 0x301008 + #define HPRE_VFG_AXQOS 0x30100c +@@ -42,7 +40,6 @@ + #define HPRE_HAC_INT_SET 0x301500 + #define HPRE_RNG_TIMEOUT_NUM 0x301A34 + #define HPRE_CORE_INT_ENABLE 0 +-#define HPRE_CORE_INT_DISABLE GENMASK(21, 0) + #define HPRE_RDCHN_INI_ST 0x301a00 + #define HPRE_CLSTR_BASE 0x302000 + #define HPRE_CORE_EN_OFFSET 0x04 +@@ -66,7 +63,6 @@ + #define HPRE_CLSTR_ADDR_INTRVL 0x1000 + #define HPRE_CLUSTER_INQURY 0x100 + #define HPRE_CLSTR_ADDR_INQRY_RSLT 0x104 +-#define HPRE_TIMEOUT_ABNML_BIT 6 + #define HPRE_PASID_EN_BIT 9 + #define HPRE_REG_RD_INTVRL_US 10 + #define HPRE_REG_RD_TMOUT_US 1000 +@@ -203,9 +199,9 @@ static const struct hisi_qm_cap_info hpre_basic_info[] = { + {HPRE_QM_RESET_MASK_CAP, 0x3128, 0, GENMASK(31, 0), 0x0, 0xC37, 0x6C37}, + {HPRE_QM_OOO_SHUTDOWN_MASK_CAP, 0x3128, 0, GENMASK(31, 0), 0x0, 0x4, 0x6C37}, + {HPRE_QM_CE_MASK_CAP, 0x312C, 0, GENMASK(31, 0), 0x0, 0x8, 0x8}, +- {HPRE_NFE_MASK_CAP, 0x3130, 0, GENMASK(31, 0), 0x0, 0x3FFFFE, 0x1FFFFFE}, +- {HPRE_RESET_MASK_CAP, 0x3134, 0, GENMASK(31, 0), 0x0, 0x3FFFFE, 0xBFFFFE}, +- {HPRE_OOO_SHUTDOWN_MASK_CAP, 0x3134, 0, GENMASK(31, 0), 0x0, 0x22, 0xBFFFFE}, ++ {HPRE_NFE_MASK_CAP, 0x3130, 0, GENMASK(31, 0), 0x0, 0x3FFFFE, 0x1FFFC3E}, ++ {HPRE_RESET_MASK_CAP, 0x3134, 0, GENMASK(31, 0), 0x0, 0x3FFFFE, 0xBFFC3E}, ++ {HPRE_OOO_SHUTDOWN_MASK_CAP, 0x3134, 0, GENMASK(31, 0), 0x0, 0x22, 0xBFFC3E}, + {HPRE_CE_MASK_CAP, 0x3138, 0, GENMASK(31, 0), 0x0, 0x1, 0x1}, + {HPRE_CLUSTER_NUM_CAP, 0x313c, 20, GENMASK(3, 0), 0x0, 0x4, 0x1}, + {HPRE_CORE_TYPE_NUM_CAP, 0x313c, 16, GENMASK(3, 0), 0x0, 0x2, 0x2}, +@@ -358,6 +354,8 @@ static struct dfx_diff_registers hpre_diff_regs[] = { + }, + }; + ++static const struct hisi_qm_err_ini hpre_err_ini; ++ + bool hpre_check_alg_support(struct hisi_qm *qm, u32 alg) + { + u32 cap_val; +@@ -654,11 +652,6 @@ static int hpre_set_user_domain_and_cache(struct hisi_qm *qm) + writel(HPRE_QM_USR_CFG_MASK, qm->io_base + QM_AWUSER_M_CFG_ENABLE); + writel_relaxed(HPRE_QM_AXI_CFG_MASK, qm->io_base + QM_AXI_M_CFG); + +- /* HPRE need more time, we close this interrupt */ +- val = readl_relaxed(qm->io_base + HPRE_QM_ABNML_INT_MASK); +- val |= BIT(HPRE_TIMEOUT_ABNML_BIT); +- writel_relaxed(val, qm->io_base + HPRE_QM_ABNML_INT_MASK); +- + if (qm->ver >= QM_HW_V3) + writel(HPRE_RSA_ENB | HPRE_ECC_ENB, + qm->io_base + HPRE_TYPES_ENB); +@@ -667,9 +660,7 @@ static int hpre_set_user_domain_and_cache(struct hisi_qm *qm) + + writel(HPRE_QM_VFG_AX_MASK, qm->io_base + HPRE_VFG_AXCACHE); + writel(0x0, qm->io_base + HPRE_BD_ENDIAN); +- writel(0x0, qm->io_base + HPRE_INT_MASK); + writel(0x0, qm->io_base + HPRE_POISON_BYPASS); +- writel(0x0, qm->io_base + HPRE_COMM_CNT_CLR_CE); + writel(0x0, qm->io_base + HPRE_ECC_BYPASS); + + writel(HPRE_BD_USR_MASK, qm->io_base + HPRE_BD_ARUSR_CFG); +@@ -759,7 +750,7 @@ static void hpre_hw_error_disable(struct hisi_qm *qm) + + static void hpre_hw_error_enable(struct hisi_qm *qm) + { +- u32 ce, nfe; ++ u32 ce, nfe, err_en; + + ce = hisi_qm_get_hw_info(qm, hpre_basic_info, HPRE_CE_MASK_CAP, qm->cap_ver); + nfe = hisi_qm_get_hw_info(qm, hpre_basic_info, HPRE_NFE_MASK_CAP, qm->cap_ver); +@@ -776,7 +767,8 @@ static void hpre_hw_error_enable(struct hisi_qm *qm) + hpre_master_ooo_ctrl(qm, true); + + /* enable hpre hw error interrupts */ +- writel(HPRE_CORE_INT_ENABLE, qm->io_base + HPRE_INT_MASK); ++ err_en = ce | nfe | HPRE_HAC_RAS_FE_ENABLE; ++ writel(~err_en, qm->io_base + HPRE_INT_MASK); + } + + static inline struct hisi_qm *hpre_file_to_qm(struct hpre_debugfs_file *file) +@@ -1161,6 +1153,7 @@ static int hpre_qm_init(struct hisi_qm *qm, struct pci_dev *pdev) + qm->qp_num = pf_q_num; + qm->debug.curr_qm_qp_num = pf_q_num; + qm->qm_list = &hpre_devices; ++ qm->err_ini = &hpre_err_ini; + if (pf_q_num_flag) + set_bit(QM_MODULE_PARAM, &qm->misc_ctl); + } +@@ -1350,8 +1343,6 @@ static int hpre_pf_probe_init(struct hpre *hpre) + + hpre_open_sva_prefetch(qm); + +- qm->err_ini = &hpre_err_ini; +- qm->err_ini->err_info_init(qm); + hisi_qm_dev_err_init(qm); + ret = hpre_show_last_regs_init(qm); + if (ret) +@@ -1380,6 +1371,18 @@ static int hpre_probe_init(struct hpre *hpre) + return 0; + } + ++static void hpre_probe_uninit(struct hisi_qm *qm) ++{ ++ if (qm->fun_type == QM_HW_VF) ++ return; ++ ++ hpre_cnt_regs_clear(qm); ++ qm->debug.curr_qm_qp_num = 0; ++ hpre_show_last_regs_uninit(qm); ++ hpre_close_sva_prefetch(qm); ++ hisi_qm_dev_err_uninit(qm); ++} ++ + static int hpre_probe(struct pci_dev *pdev, const struct pci_device_id *id) + { + struct hisi_qm *qm; +@@ -1405,7 +1408,7 @@ static int hpre_probe(struct pci_dev *pdev, const struct pci_device_id *id) + + ret = hisi_qm_start(qm); + if (ret) +- goto err_with_err_init; ++ goto err_with_probe_init; + + ret = hpre_debugfs_init(qm); + if (ret) +@@ -1444,9 +1447,8 @@ static int hpre_probe(struct pci_dev *pdev, const struct pci_device_id *id) + hpre_debugfs_exit(qm); + hisi_qm_stop(qm, QM_NORMAL); + +-err_with_err_init: +- hpre_show_last_regs_uninit(qm); +- hisi_qm_dev_err_uninit(qm); ++err_with_probe_init: ++ hpre_probe_uninit(qm); + + err_with_qm_init: + hisi_qm_uninit(qm); +@@ -1468,13 +1470,7 @@ static void hpre_remove(struct pci_dev *pdev) + hpre_debugfs_exit(qm); + hisi_qm_stop(qm, QM_NORMAL); + +- if (qm->fun_type == QM_HW_PF) { +- hpre_cnt_regs_clear(qm); +- qm->debug.curr_qm_qp_num = 0; +- hpre_show_last_regs_uninit(qm); +- hisi_qm_dev_err_uninit(qm); +- } +- ++ hpre_probe_uninit(qm); + hisi_qm_uninit(qm); + } + +diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c +index 3dac8d8e856866..da562ceaaf277f 100644 +--- a/drivers/crypto/hisilicon/qm.c ++++ b/drivers/crypto/hisilicon/qm.c +@@ -450,6 +450,7 @@ static struct qm_typical_qos_table shaper_cbs_s[] = { + }; + + static void qm_irqs_unregister(struct hisi_qm *qm); ++static int qm_reset_device(struct hisi_qm *qm); + + static u32 qm_get_hw_error_status(struct hisi_qm *qm) + { +@@ -4019,6 +4020,28 @@ static int qm_set_vf_mse(struct hisi_qm *qm, bool set) + return -ETIMEDOUT; + } + ++static void qm_dev_ecc_mbit_handle(struct hisi_qm *qm) ++{ ++ u32 nfe_enb = 0; ++ ++ /* Kunpeng930 hardware automatically close master ooo when NFE occurs */ ++ if (qm->ver >= QM_HW_V3) ++ return; ++ ++ if (!qm->err_status.is_dev_ecc_mbit && ++ qm->err_status.is_qm_ecc_mbit && ++ qm->err_ini->close_axi_master_ooo) { ++ qm->err_ini->close_axi_master_ooo(qm); ++ } else if (qm->err_status.is_dev_ecc_mbit && ++ !qm->err_status.is_qm_ecc_mbit && ++ !qm->err_ini->close_axi_master_ooo) { ++ nfe_enb = readl(qm->io_base + QM_RAS_NFE_ENABLE); ++ writel(nfe_enb & QM_RAS_NFE_MBIT_DISABLE, ++ qm->io_base + QM_RAS_NFE_ENABLE); ++ writel(QM_ECC_MBIT, qm->io_base + QM_ABNORMAL_INT_SET); ++ } ++} ++ + static int qm_vf_reset_prepare(struct hisi_qm *qm, + enum qm_stop_reason stop_reason) + { +@@ -4083,6 +4106,8 @@ static int qm_controller_reset_prepare(struct hisi_qm *qm) + return ret; + } + ++ qm_dev_ecc_mbit_handle(qm); ++ + /* PF obtains the information of VF by querying the register. */ + qm_cmd_uninit(qm); + +@@ -4113,33 +4138,26 @@ static int qm_controller_reset_prepare(struct hisi_qm *qm) + return 0; + } + +-static void qm_dev_ecc_mbit_handle(struct hisi_qm *qm) ++static int qm_master_ooo_check(struct hisi_qm *qm) + { +- u32 nfe_enb = 0; ++ u32 val; ++ int ret; + +- /* Kunpeng930 hardware automatically close master ooo when NFE occurs */ +- if (qm->ver >= QM_HW_V3) +- return; ++ /* Check the ooo register of the device before resetting the device. */ ++ writel(ACC_MASTER_GLOBAL_CTRL_SHUTDOWN, qm->io_base + ACC_MASTER_GLOBAL_CTRL); ++ ret = readl_relaxed_poll_timeout(qm->io_base + ACC_MASTER_TRANS_RETURN, ++ val, (val == ACC_MASTER_TRANS_RETURN_RW), ++ POLL_PERIOD, POLL_TIMEOUT); ++ if (ret) ++ pci_warn(qm->pdev, "Bus lock! Please reset system.\n"); + +- if (!qm->err_status.is_dev_ecc_mbit && +- qm->err_status.is_qm_ecc_mbit && +- qm->err_ini->close_axi_master_ooo) { +- qm->err_ini->close_axi_master_ooo(qm); +- } else if (qm->err_status.is_dev_ecc_mbit && +- !qm->err_status.is_qm_ecc_mbit && +- !qm->err_ini->close_axi_master_ooo) { +- nfe_enb = readl(qm->io_base + QM_RAS_NFE_ENABLE); +- writel(nfe_enb & QM_RAS_NFE_MBIT_DISABLE, +- qm->io_base + QM_RAS_NFE_ENABLE); +- writel(QM_ECC_MBIT, qm->io_base + QM_ABNORMAL_INT_SET); +- } ++ return ret; + } + +-static int qm_soft_reset(struct hisi_qm *qm) ++static int qm_soft_reset_prepare(struct hisi_qm *qm) + { + struct pci_dev *pdev = qm->pdev; + int ret; +- u32 val; + + /* Ensure all doorbells and mailboxes received by QM */ + ret = qm_check_req_recv(qm); +@@ -4160,30 +4178,23 @@ static int qm_soft_reset(struct hisi_qm *qm) + return ret; + } + +- qm_dev_ecc_mbit_handle(qm); +- +- /* OOO register set and check */ +- writel(ACC_MASTER_GLOBAL_CTRL_SHUTDOWN, +- qm->io_base + ACC_MASTER_GLOBAL_CTRL); +- +- /* If bus lock, reset chip */ +- ret = readl_relaxed_poll_timeout(qm->io_base + ACC_MASTER_TRANS_RETURN, +- val, +- (val == ACC_MASTER_TRANS_RETURN_RW), +- POLL_PERIOD, POLL_TIMEOUT); +- if (ret) { +- pci_emerg(pdev, "Bus lock! Please reset system.\n"); ++ ret = qm_master_ooo_check(qm); ++ if (ret) + return ret; +- } + + if (qm->err_ini->close_sva_prefetch) + qm->err_ini->close_sva_prefetch(qm); + + ret = qm_set_pf_mse(qm, false); +- if (ret) { ++ if (ret) + pci_err(pdev, "Fails to disable pf MSE bit.\n"); +- return ret; +- } ++ ++ return ret; ++} ++ ++static int qm_reset_device(struct hisi_qm *qm) ++{ ++ struct pci_dev *pdev = qm->pdev; + + /* The reset related sub-control registers are not in PCI BAR */ + if (ACPI_HANDLE(&pdev->dev)) { +@@ -4202,12 +4213,23 @@ static int qm_soft_reset(struct hisi_qm *qm) + pci_err(pdev, "Reset step %llu failed!\n", value); + return -EIO; + } +- } else { +- pci_err(pdev, "No reset method!\n"); +- return -EINVAL; ++ ++ return 0; + } + +- return 0; ++ pci_err(pdev, "No reset method!\n"); ++ return -EINVAL; ++} ++ ++static int qm_soft_reset(struct hisi_qm *qm) ++{ ++ int ret; ++ ++ ret = qm_soft_reset_prepare(qm); ++ if (ret) ++ return ret; ++ ++ return qm_reset_device(qm); + } + + static int qm_vf_reset_done(struct hisi_qm *qm) +@@ -5160,6 +5182,35 @@ static int qm_get_pci_res(struct hisi_qm *qm) + return ret; + } + ++static int qm_clear_device(struct hisi_qm *qm) ++{ ++ acpi_handle handle = ACPI_HANDLE(&qm->pdev->dev); ++ int ret; ++ ++ if (qm->fun_type == QM_HW_VF) ++ return 0; ++ ++ /* Device does not support reset, return */ ++ if (!qm->err_ini->err_info_init) ++ return 0; ++ qm->err_ini->err_info_init(qm); ++ ++ if (!handle) ++ return 0; ++ ++ /* No reset method, return */ ++ if (!acpi_has_method(handle, qm->err_info.acpi_rst)) ++ return 0; ++ ++ ret = qm_master_ooo_check(qm); ++ if (ret) { ++ writel(0x0, qm->io_base + ACC_MASTER_GLOBAL_CTRL); ++ return ret; ++ } ++ ++ return qm_reset_device(qm); ++} ++ + static int hisi_qm_pci_init(struct hisi_qm *qm) + { + struct pci_dev *pdev = qm->pdev; +@@ -5189,8 +5240,14 @@ static int hisi_qm_pci_init(struct hisi_qm *qm) + goto err_get_pci_res; + } + ++ ret = qm_clear_device(qm); ++ if (ret) ++ goto err_free_vectors; ++ + return 0; + ++err_free_vectors: ++ pci_free_irq_vectors(pdev); + err_get_pci_res: + qm_put_pci_res(qm); + err_disable_pcidev: +@@ -5491,7 +5548,6 @@ static int qm_prepare_for_suspend(struct hisi_qm *qm) + { + struct pci_dev *pdev = qm->pdev; + int ret; +- u32 val; + + ret = qm->ops->set_msi(qm, false); + if (ret) { +@@ -5499,18 +5555,9 @@ static int qm_prepare_for_suspend(struct hisi_qm *qm) + return ret; + } + +- /* shutdown OOO register */ +- writel(ACC_MASTER_GLOBAL_CTRL_SHUTDOWN, +- qm->io_base + ACC_MASTER_GLOBAL_CTRL); +- +- ret = readl_relaxed_poll_timeout(qm->io_base + ACC_MASTER_TRANS_RETURN, +- val, +- (val == ACC_MASTER_TRANS_RETURN_RW), +- POLL_PERIOD, POLL_TIMEOUT); +- if (ret) { +- pci_emerg(pdev, "Bus lock! Please reset system.\n"); ++ ret = qm_master_ooo_check(qm); ++ if (ret) + return ret; +- } + + ret = qm_set_pf_mse(qm, false); + if (ret) +diff --git a/drivers/crypto/hisilicon/sec2/sec_main.c b/drivers/crypto/hisilicon/sec2/sec_main.c +index 75aad04ffe5eb9..c35533d8930b21 100644 +--- a/drivers/crypto/hisilicon/sec2/sec_main.c ++++ b/drivers/crypto/hisilicon/sec2/sec_main.c +@@ -1065,9 +1065,6 @@ static int sec_pf_probe_init(struct sec_dev *sec) + struct hisi_qm *qm = &sec->qm; + int ret; + +- qm->err_ini = &sec_err_ini; +- qm->err_ini->err_info_init(qm); +- + ret = sec_set_user_domain_and_cache(qm); + if (ret) + return ret; +@@ -1122,6 +1119,7 @@ static int sec_qm_init(struct hisi_qm *qm, struct pci_dev *pdev) + qm->qp_num = pf_q_num; + qm->debug.curr_qm_qp_num = pf_q_num; + qm->qm_list = &sec_devices; ++ qm->err_ini = &sec_err_ini; + if (pf_q_num_flag) + set_bit(QM_MODULE_PARAM, &qm->misc_ctl); + } else if (qm->fun_type == QM_HW_VF && qm->ver == QM_HW_V1) { +@@ -1186,6 +1184,12 @@ static int sec_probe_init(struct sec_dev *sec) + + static void sec_probe_uninit(struct hisi_qm *qm) + { ++ if (qm->fun_type == QM_HW_VF) ++ return; ++ ++ sec_debug_regs_clear(qm); ++ sec_show_last_regs_uninit(qm); ++ sec_close_sva_prefetch(qm); + hisi_qm_dev_err_uninit(qm); + } + +@@ -1274,7 +1278,6 @@ static int sec_probe(struct pci_dev *pdev, const struct pci_device_id *id) + sec_debugfs_exit(qm); + hisi_qm_stop(qm, QM_NORMAL); + err_probe_uninit: +- sec_show_last_regs_uninit(qm); + sec_probe_uninit(qm); + err_qm_uninit: + sec_qm_uninit(qm); +@@ -1296,11 +1299,6 @@ static void sec_remove(struct pci_dev *pdev) + sec_debugfs_exit(qm); + + (void)hisi_qm_stop(qm, QM_NORMAL); +- +- if (qm->fun_type == QM_HW_PF) +- sec_debug_regs_clear(qm); +- sec_show_last_regs_uninit(qm); +- + sec_probe_uninit(qm); + + sec_qm_uninit(qm); +diff --git a/drivers/crypto/hisilicon/zip/zip_main.c b/drivers/crypto/hisilicon/zip/zip_main.c +index c94a7b20d07e6c..befef0b0e6bbe4 100644 +--- a/drivers/crypto/hisilicon/zip/zip_main.c ++++ b/drivers/crypto/hisilicon/zip/zip_main.c +@@ -1149,8 +1149,6 @@ static int hisi_zip_pf_probe_init(struct hisi_zip *hisi_zip) + + hisi_zip->ctrl = ctrl; + ctrl->hisi_zip = hisi_zip; +- qm->err_ini = &hisi_zip_err_ini; +- qm->err_ini->err_info_init(qm); + + ret = hisi_zip_set_user_domain_and_cache(qm); + if (ret) +@@ -1211,6 +1209,7 @@ static int hisi_zip_qm_init(struct hisi_qm *qm, struct pci_dev *pdev) + qm->qp_num = pf_q_num; + qm->debug.curr_qm_qp_num = pf_q_num; + qm->qm_list = &zip_devices; ++ qm->err_ini = &hisi_zip_err_ini; + if (pf_q_num_flag) + set_bit(QM_MODULE_PARAM, &qm->misc_ctl); + } else if (qm->fun_type == QM_HW_VF && qm->ver == QM_HW_V1) { +@@ -1277,6 +1276,16 @@ static int hisi_zip_probe_init(struct hisi_zip *hisi_zip) + return 0; + } + ++static void hisi_zip_probe_uninit(struct hisi_qm *qm) ++{ ++ if (qm->fun_type == QM_HW_VF) ++ return; ++ ++ hisi_zip_show_last_regs_uninit(qm); ++ hisi_zip_close_sva_prefetch(qm); ++ hisi_qm_dev_err_uninit(qm); ++} ++ + static int hisi_zip_probe(struct pci_dev *pdev, const struct pci_device_id *id) + { + struct hisi_zip *hisi_zip; +@@ -1303,7 +1312,7 @@ static int hisi_zip_probe(struct pci_dev *pdev, const struct pci_device_id *id) + + ret = hisi_qm_start(qm); + if (ret) +- goto err_dev_err_uninit; ++ goto err_probe_uninit; + + ret = hisi_zip_debugfs_init(qm); + if (ret) +@@ -1342,9 +1351,8 @@ static int hisi_zip_probe(struct pci_dev *pdev, const struct pci_device_id *id) + hisi_zip_debugfs_exit(qm); + hisi_qm_stop(qm, QM_NORMAL); + +-err_dev_err_uninit: +- hisi_zip_show_last_regs_uninit(qm); +- hisi_qm_dev_err_uninit(qm); ++err_probe_uninit: ++ hisi_zip_probe_uninit(qm); + + err_qm_uninit: + hisi_zip_qm_uninit(qm); +@@ -1366,8 +1374,7 @@ static void hisi_zip_remove(struct pci_dev *pdev) + + hisi_zip_debugfs_exit(qm); + hisi_qm_stop(qm, QM_NORMAL); +- hisi_zip_show_last_regs_uninit(qm); +- hisi_qm_dev_err_uninit(qm); ++ hisi_zip_probe_uninit(qm); + hisi_zip_qm_uninit(qm); + } + +diff --git a/drivers/crypto/intel/iaa/iaa_crypto_main.c b/drivers/crypto/intel/iaa/iaa_crypto_main.c +index e810d286ee8c42..237f8700007021 100644 +--- a/drivers/crypto/intel/iaa/iaa_crypto_main.c ++++ b/drivers/crypto/intel/iaa/iaa_crypto_main.c +@@ -495,10 +495,10 @@ static void remove_device_compression_modes(struct iaa_device *iaa_device) + if (!device_mode) + continue; + +- free_device_compression_mode(iaa_device, device_mode); +- iaa_device->compression_modes[i] = NULL; + if (iaa_compression_modes[i]->free) + iaa_compression_modes[i]->free(device_mode); ++ free_device_compression_mode(iaa_device, device_mode); ++ iaa_device->compression_modes[i] = NULL; + } + } + +diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.h b/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.h +index 8b10926cedbac2..e8c53bd76f1bd2 100644 +--- a/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.h ++++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.h +@@ -83,7 +83,7 @@ + #define ADF_WQM_CSR_RPRESETSTS(bank) (ADF_WQM_CSR_RPRESETCTL(bank) + 4) + + /* Ring interrupt */ +-#define ADF_RP_INT_SRC_SEL_F_RISE_MASK BIT(2) ++#define ADF_RP_INT_SRC_SEL_F_RISE_MASK GENMASK(1, 0) + #define ADF_RP_INT_SRC_SEL_F_FALL_MASK GENMASK(2, 0) + #define ADF_RP_INT_SRC_SEL_RANGE_WIDTH 4 + #define ADF_COALESCED_POLL_TIMEOUT_US (1 * USEC_PER_SEC) +diff --git a/drivers/crypto/intel/qat/qat_common/adf_init.c b/drivers/crypto/intel/qat/qat_common/adf_init.c +index 74f0818c070348..55f1ff1e0b3225 100644 +--- a/drivers/crypto/intel/qat/qat_common/adf_init.c ++++ b/drivers/crypto/intel/qat/qat_common/adf_init.c +@@ -323,6 +323,8 @@ static void adf_dev_stop(struct adf_accel_dev *accel_dev) + if (hw_data->stop_timer) + hw_data->stop_timer(accel_dev); + ++ hw_data->disable_iov(accel_dev); ++ + if (wait) + msleep(100); + +@@ -386,8 +388,6 @@ static void adf_dev_shutdown(struct adf_accel_dev *accel_dev) + + adf_tl_shutdown(accel_dev); + +- hw_data->disable_iov(accel_dev); +- + if (test_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status)) { + hw_data->free_irq(accel_dev); + clear_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status); +diff --git a/drivers/crypto/intel/qat/qat_common/adf_pfvf_pf_msg.c b/drivers/crypto/intel/qat/qat_common/adf_pfvf_pf_msg.c +index 0e31f4b41844e0..0cee3b23dee90b 100644 +--- a/drivers/crypto/intel/qat/qat_common/adf_pfvf_pf_msg.c ++++ b/drivers/crypto/intel/qat/qat_common/adf_pfvf_pf_msg.c +@@ -18,14 +18,17 @@ void adf_pf2vf_notify_restarting(struct adf_accel_dev *accel_dev) + + dev_dbg(&GET_DEV(accel_dev), "pf2vf notify restarting\n"); + for (i = 0, vf = accel_dev->pf.vf_info; i < num_vfs; i++, vf++) { +- vf->restarting = false; ++ if (vf->init && vf->vf_compat_ver >= ADF_PFVF_COMPAT_FALLBACK) ++ vf->restarting = true; ++ else ++ vf->restarting = false; ++ + if (!vf->init) + continue; ++ + if (adf_send_pf2vf_msg(accel_dev, i, msg)) + dev_err(&GET_DEV(accel_dev), + "Failed to send restarting msg to VF%d\n", i); +- else if (vf->vf_compat_ver >= ADF_PFVF_COMPAT_FALLBACK) +- vf->restarting = true; + } + } + +diff --git a/drivers/crypto/intel/qat/qat_common/adf_pfvf_vf_msg.c b/drivers/crypto/intel/qat/qat_common/adf_pfvf_vf_msg.c +index 1141258db4b65a..10c91e56d6be3b 100644 +--- a/drivers/crypto/intel/qat/qat_common/adf_pfvf_vf_msg.c ++++ b/drivers/crypto/intel/qat/qat_common/adf_pfvf_vf_msg.c +@@ -48,6 +48,20 @@ void adf_vf2pf_notify_shutdown(struct adf_accel_dev *accel_dev) + } + EXPORT_SYMBOL_GPL(adf_vf2pf_notify_shutdown); + ++void adf_vf2pf_notify_restart_complete(struct adf_accel_dev *accel_dev) ++{ ++ struct pfvf_message msg = { .type = ADF_VF2PF_MSGTYPE_RESTARTING_COMPLETE }; ++ ++ /* Check compatibility version */ ++ if (accel_dev->vf.pf_compat_ver < ADF_PFVF_COMPAT_FALLBACK) ++ return; ++ ++ if (adf_send_vf2pf_msg(accel_dev, msg)) ++ dev_err(&GET_DEV(accel_dev), ++ "Failed to send Restarting complete event to PF\n"); ++} ++EXPORT_SYMBOL_GPL(adf_vf2pf_notify_restart_complete); ++ + int adf_vf2pf_request_version(struct adf_accel_dev *accel_dev) + { + u8 pf_version; +diff --git a/drivers/crypto/intel/qat/qat_common/adf_pfvf_vf_msg.h b/drivers/crypto/intel/qat/qat_common/adf_pfvf_vf_msg.h +index 71bc0e3f1d9335..d79340ab3134ff 100644 +--- a/drivers/crypto/intel/qat/qat_common/adf_pfvf_vf_msg.h ++++ b/drivers/crypto/intel/qat/qat_common/adf_pfvf_vf_msg.h +@@ -6,6 +6,7 @@ + #if defined(CONFIG_PCI_IOV) + int adf_vf2pf_notify_init(struct adf_accel_dev *accel_dev); + void adf_vf2pf_notify_shutdown(struct adf_accel_dev *accel_dev); ++void adf_vf2pf_notify_restart_complete(struct adf_accel_dev *accel_dev); + int adf_vf2pf_request_version(struct adf_accel_dev *accel_dev); + int adf_vf2pf_get_capabilities(struct adf_accel_dev *accel_dev); + int adf_vf2pf_get_ring_to_svc(struct adf_accel_dev *accel_dev); +diff --git a/drivers/crypto/intel/qat/qat_common/adf_vf_isr.c b/drivers/crypto/intel/qat/qat_common/adf_vf_isr.c +index cdbb2d687b1b0d..4ab9ac33151957 100644 +--- a/drivers/crypto/intel/qat/qat_common/adf_vf_isr.c ++++ b/drivers/crypto/intel/qat/qat_common/adf_vf_isr.c +@@ -13,6 +13,7 @@ + #include "adf_cfg.h" + #include "adf_cfg_strings.h" + #include "adf_cfg_common.h" ++#include "adf_pfvf_vf_msg.h" + #include "adf_transport_access_macros.h" + #include "adf_transport_internal.h" + +@@ -75,6 +76,7 @@ static void adf_dev_stop_async(struct work_struct *work) + + /* Re-enable PF2VF interrupts */ + adf_enable_pf2vf_interrupts(accel_dev); ++ adf_vf2pf_notify_restart_complete(accel_dev); + kfree(stop_data); + } + +diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c +index 59d472cb11e750..509aeffdedc69c 100644 +--- a/drivers/crypto/n2_core.c ++++ b/drivers/crypto/n2_core.c +@@ -1357,6 +1357,7 @@ static int __n2_register_one_hmac(struct n2_ahash_alg *n2ahash) + ahash->setkey = n2_hmac_async_setkey; + + base = &ahash->halg.base; ++ err = -EINVAL; + if (snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "hmac(%s)", + p->child_alg) >= CRYPTO_MAX_ALG_NAME) + goto out_free_p; +diff --git a/drivers/crypto/qcom-rng.c b/drivers/crypto/qcom-rng.c +index c670d7d0c11ea8..6496b075a48d38 100644 +--- a/drivers/crypto/qcom-rng.c ++++ b/drivers/crypto/qcom-rng.c +@@ -196,7 +196,7 @@ static int qcom_rng_probe(struct platform_device *pdev) + if (IS_ERR(rng->clk)) + return PTR_ERR(rng->clk); + +- rng->of_data = (struct qcom_rng_of_data *)of_device_get_match_data(&pdev->dev); ++ rng->of_data = (struct qcom_rng_of_data *)device_get_match_data(&pdev->dev); + + qcom_rng_dev = rng; + ret = crypto_register_rng(&qcom_rng_alg); +@@ -247,7 +247,7 @@ static struct qcom_rng_of_data qcom_trng_of_data = { + }; + + static const struct acpi_device_id __maybe_unused qcom_rng_acpi_match[] = { +- { .id = "QCOM8160", .driver_data = 1 }, ++ { .id = "QCOM8160", .driver_data = (kernel_ulong_t)&qcom_prng_ee_of_data }, + {} + }; + MODULE_DEVICE_TABLE(acpi, qcom_rng_acpi_match); +diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c +index 8567dd11eaac74..205085ccf12c30 100644 +--- a/drivers/cxl/core/pci.c ++++ b/drivers/cxl/core/pci.c +@@ -390,10 +390,6 @@ int cxl_dvsec_rr_decode(struct device *dev, int d, + + size |= temp & CXL_DVSEC_MEM_SIZE_LOW_MASK; + if (!size) { +- info->dvsec_range[i] = (struct range) { +- .start = 0, +- .end = CXL_RESOURCE_NONE, +- }; + continue; + } + +@@ -411,12 +407,10 @@ int cxl_dvsec_rr_decode(struct device *dev, int d, + + base |= temp & CXL_DVSEC_MEM_BASE_LOW_MASK; + +- info->dvsec_range[i] = (struct range) { ++ info->dvsec_range[ranges++] = (struct range) { + .start = base, + .end = base + size - 1 + }; +- +- ranges++; + } + + info->ranges = ranges; +diff --git a/drivers/edac/igen6_edac.c b/drivers/edac/igen6_edac.c +index dbe9fe5f2ca6c3..594408aa934bf5 100644 +--- a/drivers/edac/igen6_edac.c ++++ b/drivers/edac/igen6_edac.c +@@ -311,7 +311,7 @@ static u64 ehl_err_addr_to_imc_addr(u64 eaddr, int mc) + if (igen6_tom <= _4GB) + return eaddr + igen6_tolud - _4GB; + +- if (eaddr < _4GB) ++ if (eaddr >= igen6_tom) + return eaddr + igen6_tolud - igen6_tom; + + return eaddr; +diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c +index ea7a9a342dd30b..d7416166fd8a42 100644 +--- a/drivers/edac/synopsys_edac.c ++++ b/drivers/edac/synopsys_edac.c +@@ -10,6 +10,7 @@ + #include <linux/module.h> + #include <linux/platform_device.h> + #include <linux/spinlock.h> ++#include <linux/sizes.h> + #include <linux/interrupt.h> + #include <linux/of.h> + +@@ -337,6 +338,7 @@ struct synps_edac_priv { + * @get_mtype: Get mtype. + * @get_dtype: Get dtype. + * @get_ecc_state: Get ECC state. ++ * @get_mem_info: Get EDAC memory info + * @quirks: To differentiate IPs. + */ + struct synps_platform_data { +@@ -344,6 +346,9 @@ struct synps_platform_data { + enum mem_type (*get_mtype)(const void __iomem *base); + enum dev_type (*get_dtype)(const void __iomem *base); + bool (*get_ecc_state)(void __iomem *base); ++#ifdef CONFIG_EDAC_DEBUG ++ u64 (*get_mem_info)(struct synps_edac_priv *priv); ++#endif + int quirks; + }; + +@@ -402,6 +407,25 @@ static int zynq_get_error_info(struct synps_edac_priv *priv) + return 0; + } + ++#ifdef CONFIG_EDAC_DEBUG ++/** ++ * zynqmp_get_mem_info - Get the current memory info. ++ * @priv: DDR memory controller private instance data. ++ * ++ * Return: host interface address. ++ */ ++static u64 zynqmp_get_mem_info(struct synps_edac_priv *priv) ++{ ++ u64 hif_addr = 0, linear_addr; ++ ++ linear_addr = priv->poison_addr; ++ if (linear_addr >= SZ_32G) ++ linear_addr = linear_addr - SZ_32G + SZ_2G; ++ hif_addr = linear_addr >> 3; ++ return hif_addr; ++} ++#endif ++ + /** + * zynqmp_get_error_info - Get the current ECC error info. + * @priv: DDR memory controller private instance data. +@@ -922,6 +946,9 @@ static const struct synps_platform_data zynqmp_edac_def = { + .get_mtype = zynqmp_get_mtype, + .get_dtype = zynqmp_get_dtype, + .get_ecc_state = zynqmp_get_ecc_state, ++#ifdef CONFIG_EDAC_DEBUG ++ .get_mem_info = zynqmp_get_mem_info, ++#endif + .quirks = (DDR_ECC_INTR_SUPPORT + #ifdef CONFIG_EDAC_DEBUG + | DDR_ECC_DATA_POISON_SUPPORT +@@ -975,10 +1002,16 @@ MODULE_DEVICE_TABLE(of, synps_edac_match); + static void ddr_poison_setup(struct synps_edac_priv *priv) + { + int col = 0, row = 0, bank = 0, bankgrp = 0, rank = 0, regval; ++ const struct synps_platform_data *p_data; + int index; + ulong hif_addr = 0; + +- hif_addr = priv->poison_addr >> 3; ++ p_data = priv->p_data; ++ ++ if (p_data->get_mem_info) ++ hif_addr = p_data->get_mem_info(priv); ++ else ++ hif_addr = priv->poison_addr >> 3; + + for (index = 0; index < DDR_MAX_ROW_SHIFT; index++) { + if (priv->row_shift[index]) +diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c +index 9a7dc90330a351..a888a001bedb15 100644 +--- a/drivers/firewire/core-cdev.c ++++ b/drivers/firewire/core-cdev.c +@@ -599,11 +599,11 @@ static void complete_transaction(struct fw_card *card, int rcode, u32 request_ts + queue_event(client, &e->event, rsp, sizeof(*rsp) + rsp->length, NULL, 0); + + break; ++ } + default: + WARN_ON(1); + break; + } +- } + + /* Drop the idr's reference */ + client_put(client); +diff --git a/drivers/firmware/arm_scmi/optee.c b/drivers/firmware/arm_scmi/optee.c +index 4e7944b91e3857..0c8908d3b1d678 100644 +--- a/drivers/firmware/arm_scmi/optee.c ++++ b/drivers/firmware/arm_scmi/optee.c +@@ -473,6 +473,13 @@ static int scmi_optee_chan_free(int id, void *p, void *data) + struct scmi_chan_info *cinfo = p; + struct scmi_optee_channel *channel = cinfo->transport_info; + ++ /* ++ * Different protocols might share the same chan info, so a previous ++ * call might have already freed the structure. ++ */ ++ if (!channel) ++ return 0; ++ + mutex_lock(&scmi_optee_private->mu); + list_del(&channel->link); + mutex_unlock(&scmi_optee_private->mu); +diff --git a/drivers/firmware/efi/libstub/tpm.c b/drivers/firmware/efi/libstub/tpm.c +index df3182f2e63a56..1fd6823248ab6e 100644 +--- a/drivers/firmware/efi/libstub/tpm.c ++++ b/drivers/firmware/efi/libstub/tpm.c +@@ -96,7 +96,7 @@ static void efi_retrieve_tcg2_eventlog(int version, efi_physical_addr_t log_loca + } + + /* Allocate space for the logs and copy them. */ +- status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, ++ status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY, + sizeof(*log_tbl) + log_size, (void **)&log_tbl); + + if (status != EFI_SUCCESS) { +diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c +index 68f4df7e6c3c7f..77dd831febf5bc 100644 +--- a/drivers/firmware/qcom/qcom_scm.c ++++ b/drivers/firmware/qcom/qcom_scm.c +@@ -1875,14 +1875,12 @@ static int qcom_scm_probe(struct platform_device *pdev) + * will cause the boot stages to enter download mode, unless + * disabled below by a clean shutdown/reboot. + */ +- if (download_mode) +- qcom_scm_set_download_mode(true); +- ++ qcom_scm_set_download_mode(download_mode); + + /* + * Disable SDI if indicated by DT that it is enabled by default. + */ +- if (of_property_read_bool(pdev->dev.of_node, "qcom,sdi-enabled")) ++ if (of_property_read_bool(pdev->dev.of_node, "qcom,sdi-enabled") || !download_mode) + qcom_scm_disable_sdi(); + + /* +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +index 0f7106066480ea..3fdbc10aebce1d 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +@@ -902,10 +902,12 @@ amdgpu_vm_tlb_flush(struct amdgpu_vm_update_params *params, + { + struct amdgpu_vm *vm = params->vm; + +- if (!fence || !*fence) ++ tlb_cb->vm = vm; ++ if (!fence || !*fence) { ++ amdgpu_vm_tlb_seq_cb(NULL, &tlb_cb->cb); + return; ++ } + +- tlb_cb->vm = vm; + if (!dma_fence_add_callback(*fence, &tlb_cb->cb, + amdgpu_vm_tlb_seq_cb)) { + dma_fence_put(vm->last_tlb_flush); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h +index fb2b394bb9c555..6e9eeaeb3de1dd 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h +@@ -213,7 +213,7 @@ struct amd_sriov_msg_pf2vf_info { + uint32_t gpu_capacity; + /* reserved */ + uint32_t reserved[256 - AMD_SRIOV_MSG_PF2VF_INFO_FILLED_SIZE]; +-}; ++} __packed; + + struct amd_sriov_msg_vf2pf_info_header { + /* the total structure size in byte */ +@@ -273,7 +273,7 @@ struct amd_sriov_msg_vf2pf_info { + uint32_t mes_info_size; + /* reserved */ + uint32_t reserved[256 - AMD_SRIOV_MSG_VF2PF_INFO_FILLED_SIZE]; +-}; ++} __packed; + + /* mailbox message send from guest to host */ + enum amd_sriov_mailbox_request_message { +diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c +index 25feab188dfe69..ebf83fee43bb99 100644 +--- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c ++++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c +@@ -2065,26 +2065,29 @@ amdgpu_atombios_encoder_get_lcd_info(struct amdgpu_encoder *encoder) + fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record; + if (fake_edid_record->ucFakeEDIDLength) { + struct edid *edid; +- int edid_size = +- max((int)EDID_LENGTH, (int)fake_edid_record->ucFakeEDIDLength); +- edid = kmalloc(edid_size, GFP_KERNEL); ++ int edid_size; ++ ++ if (fake_edid_record->ucFakeEDIDLength == 128) ++ edid_size = fake_edid_record->ucFakeEDIDLength; ++ else ++ edid_size = fake_edid_record->ucFakeEDIDLength * 128; ++ edid = kmemdup(&fake_edid_record->ucFakeEDIDString[0], ++ edid_size, GFP_KERNEL); + if (edid) { +- memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0], +- fake_edid_record->ucFakeEDIDLength); +- + if (drm_edid_is_valid(edid)) { + adev->mode_info.bios_hardcoded_edid = edid; + adev->mode_info.bios_hardcoded_edid_size = edid_size; +- } else ++ } else { + kfree(edid); ++ } + } ++ record += struct_size(fake_edid_record, ++ ucFakeEDIDString, ++ edid_size); ++ } else { ++ /* empty fake edid record must be 3 bytes long */ ++ record += sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + 1; + } +- record += fake_edid_record->ucFakeEDIDLength ? +- struct_size(fake_edid_record, +- ucFakeEDIDString, +- fake_edid_record->ucFakeEDIDLength) : +- /* empty fake edid record must be 3 bytes long */ +- sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + 1; + break; + case LCD_PANEL_RESOLUTION_RECORD_TYPE: + panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record; +diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +index e1a66d585f5e99..44b277c55de4a5 100644 +--- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +@@ -155,7 +155,7 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, + int api_status_off) + { + union MESAPI__QUERY_MES_STATUS mes_status_pkt; +- signed long timeout = 3000000; /* 3000 ms */ ++ signed long timeout = 2100000; /* 2100 ms */ + struct amdgpu_device *adev = mes->adev; + struct amdgpu_ring *ring = &mes->ring; + struct MES_API_STATUS *api_status; +diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c +index 30e80c6f11ed68..68ac91d28ded0f 100644 +--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c ++++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c +@@ -1353,170 +1353,6 @@ static void vcn_v4_0_5_unified_ring_set_wptr(struct amdgpu_ring *ring) + } + } + +-static int vcn_v4_0_5_limit_sched(struct amdgpu_cs_parser *p, +- struct amdgpu_job *job) +-{ +- struct drm_gpu_scheduler **scheds; +- +- /* The create msg must be in the first IB submitted */ +- if (atomic_read(&job->base.entity->fence_seq)) +- return -EINVAL; +- +- /* if VCN0 is harvested, we can't support AV1 */ +- if (p->adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) +- return -EINVAL; +- +- scheds = p->adev->gpu_sched[AMDGPU_HW_IP_VCN_ENC] +- [AMDGPU_RING_PRIO_0].sched; +- drm_sched_entity_modify_sched(job->base.entity, scheds, 1); +- return 0; +-} +- +-static int vcn_v4_0_5_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job, +- uint64_t addr) +-{ +- struct ttm_operation_ctx ctx = { false, false }; +- struct amdgpu_bo_va_mapping *map; +- uint32_t *msg, num_buffers; +- struct amdgpu_bo *bo; +- uint64_t start, end; +- unsigned int i; +- void *ptr; +- int r; +- +- addr &= AMDGPU_GMC_HOLE_MASK; +- r = amdgpu_cs_find_mapping(p, addr, &bo, &map); +- if (r) { +- DRM_ERROR("Can't find BO for addr 0x%08llx\n", addr); +- return r; +- } +- +- start = map->start * AMDGPU_GPU_PAGE_SIZE; +- end = (map->last + 1) * AMDGPU_GPU_PAGE_SIZE; +- if (addr & 0x7) { +- DRM_ERROR("VCN messages must be 8 byte aligned!\n"); +- return -EINVAL; +- } +- +- bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; +- amdgpu_bo_placement_from_domain(bo, bo->allowed_domains); +- r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); +- if (r) { +- DRM_ERROR("Failed validating the VCN message BO (%d)!\n", r); +- return r; +- } +- +- r = amdgpu_bo_kmap(bo, &ptr); +- if (r) { +- DRM_ERROR("Failed mapping the VCN message (%d)!\n", r); +- return r; +- } +- +- msg = ptr + addr - start; +- +- /* Check length */ +- if (msg[1] > end - addr) { +- r = -EINVAL; +- goto out; +- } +- +- if (msg[3] != RDECODE_MSG_CREATE) +- goto out; +- +- num_buffers = msg[2]; +- for (i = 0, msg = &msg[6]; i < num_buffers; ++i, msg += 4) { +- uint32_t offset, size, *create; +- +- if (msg[0] != RDECODE_MESSAGE_CREATE) +- continue; +- +- offset = msg[1]; +- size = msg[2]; +- +- if (offset + size > end) { +- r = -EINVAL; +- goto out; +- } +- +- create = ptr + addr + offset - start; +- +- /* H264, HEVC and VP9 can run on any instance */ +- if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11) +- continue; +- +- r = vcn_v4_0_5_limit_sched(p, job); +- if (r) +- goto out; +- } +- +-out: +- amdgpu_bo_kunmap(bo); +- return r; +-} +- +-#define RADEON_VCN_ENGINE_TYPE_ENCODE (0x00000002) +-#define RADEON_VCN_ENGINE_TYPE_DECODE (0x00000003) +- +-#define RADEON_VCN_ENGINE_INFO (0x30000001) +-#define RADEON_VCN_ENGINE_INFO_MAX_OFFSET 16 +- +-#define RENCODE_ENCODE_STANDARD_AV1 2 +-#define RENCODE_IB_PARAM_SESSION_INIT 0x00000003 +-#define RENCODE_IB_PARAM_SESSION_INIT_MAX_OFFSET 64 +- +-/* return the offset in ib if id is found, -1 otherwise +- * to speed up the searching we only search upto max_offset +- */ +-static int vcn_v4_0_5_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int max_offset) +-{ +- int i; +- +- for (i = 0; i < ib->length_dw && i < max_offset && ib->ptr[i] >= 8; i += ib->ptr[i]/4) { +- if (ib->ptr[i + 1] == id) +- return i; +- } +- return -1; +-} +- +-static int vcn_v4_0_5_ring_patch_cs_in_place(struct amdgpu_cs_parser *p, +- struct amdgpu_job *job, +- struct amdgpu_ib *ib) +-{ +- struct amdgpu_ring *ring = amdgpu_job_ring(job); +- struct amdgpu_vcn_decode_buffer *decode_buffer; +- uint64_t addr; +- uint32_t val; +- int idx; +- +- /* The first instance can decode anything */ +- if (!ring->me) +- return 0; +- +- /* RADEON_VCN_ENGINE_INFO is at the top of ib block */ +- idx = vcn_v4_0_5_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, +- RADEON_VCN_ENGINE_INFO_MAX_OFFSET); +- if (idx < 0) /* engine info is missing */ +- return 0; +- +- val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */ +- if (val == RADEON_VCN_ENGINE_TYPE_DECODE) { +- decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6]; +- +- if (!(decode_buffer->valid_buf_flag & 0x1)) +- return 0; +- +- addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 | +- decode_buffer->msg_buffer_address_lo; +- return vcn_v4_0_5_dec_msg(p, job, addr); +- } else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) { +- idx = vcn_v4_0_5_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, +- RENCODE_IB_PARAM_SESSION_INIT_MAX_OFFSET); +- if (idx >= 0 && ib->ptr[idx + 2] == RENCODE_ENCODE_STANDARD_AV1) +- return vcn_v4_0_5_limit_sched(p, job); +- } +- return 0; +-} +- + static const struct amdgpu_ring_funcs vcn_v4_0_5_unified_ring_vm_funcs = { + .type = AMDGPU_RING_TYPE_VCN_ENC, + .align_mask = 0x3f, +@@ -1524,7 +1360,6 @@ static const struct amdgpu_ring_funcs vcn_v4_0_5_unified_ring_vm_funcs = { + .get_rptr = vcn_v4_0_5_unified_ring_get_rptr, + .get_wptr = vcn_v4_0_5_unified_ring_get_wptr, + .set_wptr = vcn_v4_0_5_unified_ring_set_wptr, +- .patch_cs_in_place = vcn_v4_0_5_ring_patch_cs_in_place, + .emit_frame_size = + SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 + + SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 4 + +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 27e641f176289a..3541d154cc8d06 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -4149,6 +4149,7 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) + + #define AMDGPU_DM_DEFAULT_MIN_BACKLIGHT 12 + #define AMDGPU_DM_DEFAULT_MAX_BACKLIGHT 255 ++#define AMDGPU_DM_MIN_SPREAD ((AMDGPU_DM_DEFAULT_MAX_BACKLIGHT - AMDGPU_DM_DEFAULT_MIN_BACKLIGHT) / 2) + #define AUX_BL_DEFAULT_TRANSITION_TIME_MS 50 + + static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm, +@@ -4163,6 +4164,21 @@ static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm, + return; + + amdgpu_acpi_get_backlight_caps(&caps); ++ ++ /* validate the firmware value is sane */ ++ if (caps.caps_valid) { ++ int spread = caps.max_input_signal - caps.min_input_signal; ++ ++ if (caps.max_input_signal > AMDGPU_DM_DEFAULT_MAX_BACKLIGHT || ++ caps.min_input_signal < AMDGPU_DM_DEFAULT_MIN_BACKLIGHT || ++ spread > AMDGPU_DM_DEFAULT_MAX_BACKLIGHT || ++ spread < AMDGPU_DM_MIN_SPREAD) { ++ DRM_DEBUG_KMS("DM: Invalid backlight caps: min=%d, max=%d\n", ++ caps.min_input_signal, caps.max_input_signal); ++ caps.caps_valid = false; ++ } ++ } ++ + if (caps.caps_valid) { + dm->backlight_caps[bl_idx].caps_valid = true; + if (caps.aux_support) +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +index b50010ed763327..9a620773141682 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +@@ -251,7 +251,7 @@ static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnecto + aconnector->dsc_aux = &aconnector->mst_root->dm_dp_aux.aux; + + /* synaptics cascaded MST hub case */ +- if (!aconnector->dsc_aux && is_synaptics_cascaded_panamera(aconnector->dc_link, port)) ++ if (is_synaptics_cascaded_panamera(aconnector->dc_link, port)) + aconnector->dsc_aux = port->mgr->aux; + + if (!aconnector->dsc_aux) +@@ -1111,7 +1111,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, + params[count].num_slices_v = aconnector->dsc_settings.dsc_num_slices_v; + params[count].bpp_overwrite = aconnector->dsc_settings.dsc_bits_per_pixel; + params[count].compression_possible = stream->sink->dsc_caps.dsc_dec_caps.is_dsc_supported; +- dc_dsc_get_policy_for_timing(params[count].timing, 0, &dsc_policy); ++ dc_dsc_get_policy_for_timing(params[count].timing, 0, &dsc_policy, dc_link_get_highest_encoding_format(stream->link)); + if (!dc_dsc_compute_bandwidth_range( + stream->sink->ctx->dc->res_pool->dscs[0], + stream->sink->ctx->dc->debug.dsc_min_slice_height_override, +@@ -1264,6 +1264,9 @@ static bool is_dsc_need_re_compute( + } + } + ++ if (new_stream_on_link_num == 0) ++ return false; ++ + if (new_stream_on_link_num == 0) + return false; + +@@ -1583,7 +1586,7 @@ static bool is_dsc_common_config_possible(struct dc_stream_state *stream, + { + struct dc_dsc_policy dsc_policy = {0}; + +- dc_dsc_get_policy_for_timing(&stream->timing, 0, &dsc_policy); ++ dc_dsc_get_policy_for_timing(&stream->timing, 0, &dsc_policy, dc_link_get_highest_encoding_format(stream->link)); + dc_dsc_compute_bandwidth_range(stream->sink->ctx->dc->res_pool->dscs[0], + stream->sink->ctx->dc->debug.dsc_min_slice_height_override, + dsc_policy.min_target_bpp * 16, +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +index 6c9b4e6491a5e4..985e847f958032 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +@@ -1149,6 +1149,12 @@ void dcn35_clk_mgr_construct( + ctx->dc->debug.disable_dpp_power_gate = false; + ctx->dc->debug.disable_hubp_power_gate = false; + ctx->dc->debug.disable_dsc_power_gate = false; ++ ++ /* Disable dynamic IPS2 in older PMFW (93.12) for Z8 interop. */ ++ if (ctx->dc->config.disable_ips == DMUB_IPS_ENABLE && ++ ctx->dce_version == DCN_VERSION_3_5 && ++ ((clk_mgr->base.smu_ver & 0x00FFFFFF) <= 0x005d0c00)) ++ ctx->dc->config.disable_ips = DMUB_IPS_RCG_IN_ACTIVE_IPS2_IN_OFF; + } else { + /*let's reset the config control flag*/ + ctx->dc->config.disable_ips = DMUB_IPS_DISABLE_ALL; /*pmfw not support it, disable it all*/ +diff --git a/drivers/gpu/drm/amd/display/dc/dc_dsc.h b/drivers/gpu/drm/amd/display/dc/dc_dsc.h +index fe3078b8789ef1..01c07545ef6b47 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_dsc.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_dsc.h +@@ -100,7 +100,8 @@ uint32_t dc_dsc_stream_bandwidth_overhead_in_kbps( + */ + void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing, + uint32_t max_target_bpp_limit_override_x16, +- struct dc_dsc_policy *policy); ++ struct dc_dsc_policy *policy, ++ const enum dc_link_encoding_format link_encoding); + + void dc_dsc_policy_set_max_target_bpp_limit(uint32_t limit); + +diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c +index 150ef23440a2c1..f8c1e1ca678bf1 100644 +--- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c ++++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c +@@ -883,7 +883,7 @@ static bool setup_dsc_config( + + memset(dsc_cfg, 0, sizeof(struct dc_dsc_config)); + +- dc_dsc_get_policy_for_timing(timing, options->max_target_bpp_limit_override_x16, &policy); ++ dc_dsc_get_policy_for_timing(timing, options->max_target_bpp_limit_override_x16, &policy, link_encoding); + pic_width = timing->h_addressable + timing->h_border_left + timing->h_border_right; + pic_height = timing->v_addressable + timing->v_border_top + timing->v_border_bottom; + +@@ -1156,7 +1156,8 @@ uint32_t dc_dsc_stream_bandwidth_overhead_in_kbps( + + void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing, + uint32_t max_target_bpp_limit_override_x16, +- struct dc_dsc_policy *policy) ++ struct dc_dsc_policy *policy, ++ const enum dc_link_encoding_format link_encoding) + { + uint32_t bpc = 0; + +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 0d3ea291eeee18..e9e9f80a02a775 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 +@@ -57,6 +57,7 @@ + #include "panel_cntl.h" + #include "dc_state_priv.h" + #include "dpcd_defs.h" ++#include "dsc.h" + /* include DCE11 register header files */ + #include "dce/dce_11_0_d.h" + #include "dce/dce_11_0_sh_mask.h" +@@ -1768,6 +1769,48 @@ static void get_edp_links_with_sink( + } + } + ++static void clean_up_dsc_blocks(struct dc *dc) ++{ ++ struct display_stream_compressor *dsc = NULL; ++ struct timing_generator *tg = NULL; ++ struct stream_encoder *se = NULL; ++ struct dccg *dccg = dc->res_pool->dccg; ++ struct pg_cntl *pg_cntl = dc->res_pool->pg_cntl; ++ int i; ++ ++ if (dc->ctx->dce_version != DCN_VERSION_3_5 && ++ dc->ctx->dce_version != DCN_VERSION_3_51) ++ return; ++ ++ for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) { ++ struct dcn_dsc_state s = {0}; ++ ++ dsc = dc->res_pool->dscs[i]; ++ dsc->funcs->dsc_read_state(dsc, &s); ++ if (s.dsc_fw_en) { ++ /* disable DSC in OPTC */ ++ if (i < dc->res_pool->timing_generator_count) { ++ tg = dc->res_pool->timing_generators[i]; ++ tg->funcs->set_dsc_config(tg, OPTC_DSC_DISABLED, 0, 0); ++ } ++ /* disable DSC in stream encoder */ ++ if (i < dc->res_pool->stream_enc_count) { ++ se = dc->res_pool->stream_enc[i]; ++ se->funcs->dp_set_dsc_config(se, OPTC_DSC_DISABLED, 0, 0); ++ se->funcs->dp_set_dsc_pps_info_packet(se, false, NULL, true); ++ } ++ /* disable DSC block */ ++ if (dccg->funcs->set_ref_dscclk) ++ dccg->funcs->set_ref_dscclk(dccg, dsc->inst); ++ dsc->funcs->dsc_disable(dsc); ++ ++ /* power down DSC */ ++ if (pg_cntl != NULL) ++ pg_cntl->funcs->dsc_pg_control(pg_cntl, dsc->inst, false); ++ } ++ } ++} ++ + /* + * When ASIC goes from VBIOS/VGA mode to driver/accelerated mode we need: + * 1. Power down all DC HW blocks +@@ -1852,6 +1895,13 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) + clk_mgr_exit_optimized_pwr_state(dc, dc->clk_mgr); + + power_down_all_hw_blocks(dc); ++ ++ /* DSC could be enabled on eDP during VBIOS post. ++ * To clean up dsc blocks if eDP is in link but not active. ++ */ ++ if (edp_link_with_sink && (edp_stream_num == 0)) ++ clean_up_dsc_blocks(dc); ++ + disable_vga_and_power_gate_all_controllers(dc); + if (edp_link_with_sink && !keep_edp_vdd_on) + dc->hwss.edp_power_control(edp_link_with_sink, false); +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c +index 4c470615330509..05c5d4f04e1bd8 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c +@@ -395,7 +395,11 @@ bool dcn30_set_output_transfer_func(struct dc *dc, + } + } + +- mpc->funcs->set_output_gamma(mpc, mpcc_id, params); ++ if (mpc->funcs->set_output_gamma) ++ mpc->funcs->set_output_gamma(mpc, mpcc_id, params); ++ else ++ DC_LOG_ERROR("%s: set_output_gamma function pointer is NULL.\n", __func__); ++ + return ret; + } + +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c +index b8e884368dc6e5..5fc377f51f5621 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c +@@ -991,6 +991,20 @@ static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) + struct dsc_config dsc_cfg; + struct dsc_optc_config dsc_optc_cfg = {0}; + enum optc_dsc_mode optc_dsc_mode; ++ struct dcn_dsc_state dsc_state = {0}; ++ ++ if (!dsc) { ++ DC_LOG_DSC("DSC is NULL for tg instance %d:", pipe_ctx->stream_res.tg->inst); ++ return; ++ } ++ ++ if (dsc->funcs->dsc_read_state) { ++ dsc->funcs->dsc_read_state(dsc, &dsc_state); ++ if (!dsc_state.dsc_fw_en) { ++ DC_LOG_DSC("DSC has been disabled for tg instance %d:", pipe_ctx->stream_res.tg->inst); ++ return; ++ } ++ } + + /* Enable DSC hw block */ + dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt; +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +index 4f0e9e0f701dd2..900dfc0f275373 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +@@ -375,7 +375,20 @@ static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) + struct dsc_config dsc_cfg; + struct dsc_optc_config dsc_optc_cfg = {0}; + enum optc_dsc_mode optc_dsc_mode; ++ struct dcn_dsc_state dsc_state = {0}; + ++ if (!dsc) { ++ DC_LOG_DSC("DSC is NULL for tg instance %d:", pipe_ctx->stream_res.tg->inst); ++ return; ++ } ++ ++ if (dsc->funcs->dsc_read_state) { ++ dsc->funcs->dsc_read_state(dsc, &dsc_state); ++ if (!dsc_state.dsc_fw_en) { ++ DC_LOG_DSC("DSC has been disabled for tg instance %d:", pipe_ctx->stream_res.tg->inst); ++ return; ++ } ++ } + /* Enable DSC hw block */ + dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt; + dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom; +diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c +index 915d68cc04e9c2..66b73edda7b6dd 100644 +--- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c +@@ -2150,6 +2150,7 @@ static bool dcn35_resource_construct( + dc->dml2_options.max_segments_per_hubp = 24; + + dc->dml2_options.det_segment_size = DCN3_2_DET_SEG_SIZE;/*todo*/ ++ dc->dml2_options.override_det_buffer_size_kbytes = true; + + if (dc->config.sdpif_request_limit_words_per_umc == 0) + dc->config.sdpif_request_limit_words_per_umc = 16;/*todo*/ +diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c +index b7bd0f36125a4d..987c3927b11851 100644 +--- a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c +@@ -736,7 +736,7 @@ static const struct dc_debug_options debug_defaults_drv = { + .hdmichar = true, + .dpstream = true, + .symclk32_se = true, +- .symclk32_le = true, ++ .symclk32_le = false, + .symclk_fe = true, + .physymclk = true, + .dpiasymclk = true, +@@ -2132,6 +2132,7 @@ static bool dcn351_resource_construct( + + dc->dml2_options.max_segments_per_hubp = 24; + dc->dml2_options.det_segment_size = DCN3_2_DET_SEG_SIZE;/*todo*/ ++ dc->dml2_options.override_det_buffer_size_kbytes = true; + + if (dc->config.sdpif_request_limit_words_per_umc == 0) + dc->config.sdpif_request_limit_words_per_umc = 16;/*todo*/ +diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +index d09627c15b9c22..2b8d09bb0cc158 100644 +--- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c ++++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +@@ -134,7 +134,7 @@ unsigned int mod_freesync_calc_v_total_from_refresh( + + v_total = div64_u64(div64_u64(((unsigned long long)( + frame_duration_in_ns) * (stream->timing.pix_clk_100hz / 10)), +- stream->timing.h_total), 1000000); ++ stream->timing.h_total) + 500000, 1000000); + + /* v_total cannot be less than nominal */ + if (v_total < stream->timing.v_total) { +diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c +index 1a9defa15663cf..e265ab3c8c9293 100644 +--- a/drivers/gpu/drm/bridge/lontium-lt8912b.c ++++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c +@@ -422,22 +422,6 @@ static const struct drm_connector_funcs lt8912_connector_funcs = { + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, + }; + +-static enum drm_mode_status +-lt8912_connector_mode_valid(struct drm_connector *connector, +- struct drm_display_mode *mode) +-{ +- if (mode->clock > 150000) +- return MODE_CLOCK_HIGH; +- +- if (mode->hdisplay > 1920) +- return MODE_BAD_HVALUE; +- +- if (mode->vdisplay > 1080) +- return MODE_BAD_VVALUE; +- +- return MODE_OK; +-} +- + static int lt8912_connector_get_modes(struct drm_connector *connector) + { + const struct drm_edid *drm_edid; +@@ -463,7 +447,6 @@ static int lt8912_connector_get_modes(struct drm_connector *connector) + + static const struct drm_connector_helper_funcs lt8912_connector_helper_funcs = { + .get_modes = lt8912_connector_get_modes, +- .mode_valid = lt8912_connector_mode_valid, + }; + + static void lt8912_bridge_mode_set(struct drm_bridge *bridge, +@@ -605,6 +588,23 @@ static void lt8912_bridge_detach(struct drm_bridge *bridge) + drm_bridge_hpd_disable(lt->hdmi_port); + } + ++static enum drm_mode_status ++lt8912_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, ++ const struct drm_display_mode *mode) ++{ ++ if (mode->clock > 150000) ++ return MODE_CLOCK_HIGH; ++ ++ if (mode->hdisplay > 1920) ++ return MODE_BAD_HVALUE; ++ ++ if (mode->vdisplay > 1080) ++ return MODE_BAD_VVALUE; ++ ++ return MODE_OK; ++} ++ + static enum drm_connector_status + lt8912_bridge_detect(struct drm_bridge *bridge) + { +@@ -635,6 +635,7 @@ static const struct drm_edid *lt8912_bridge_edid_read(struct drm_bridge *bridge, + static const struct drm_bridge_funcs lt8912_bridge_funcs = { + .attach = lt8912_bridge_attach, + .detach = lt8912_bridge_detach, ++ .mode_valid = lt8912_bridge_mode_valid, + .mode_set = lt8912_bridge_mode_set, + .enable = lt8912_bridge_enable, + .detect = lt8912_bridge_detect, +diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c +index 1b111e2c33472b..752339d33f39a5 100644 +--- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c ++++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c +@@ -1174,7 +1174,7 @@ static int gsc_bind(struct device *dev, struct device *master, void *data) + struct exynos_drm_ipp *ipp = &ctx->ipp; + + ctx->drm_dev = drm_dev; +- ctx->drm_dev = drm_dev; ++ ipp->drm_dev = drm_dev; + exynos_drm_register_dma(drm_dev, dev, &ctx->dma_priv); + + exynos_drm_ipp_register(dev, ipp, &ipp_funcs, +diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c +index 6f34f573e127ec..a90504359e8d27 100644 +--- a/drivers/gpu/drm/mediatek/mtk_crtc.c ++++ b/drivers/gpu/drm/mediatek/mtk_crtc.c +@@ -69,6 +69,8 @@ struct mtk_crtc { + /* lock for display hardware access */ + struct mutex hw_lock; + bool config_updating; ++ /* lock for config_updating to cmd buffer */ ++ spinlock_t config_lock; + }; + + struct mtk_crtc_state { +@@ -106,11 +108,16 @@ static void mtk_crtc_finish_page_flip(struct mtk_crtc *mtk_crtc) + + static void mtk_drm_finish_page_flip(struct mtk_crtc *mtk_crtc) + { ++ unsigned long flags; ++ + drm_crtc_handle_vblank(&mtk_crtc->base); ++ ++ spin_lock_irqsave(&mtk_crtc->config_lock, flags); + if (!mtk_crtc->config_updating && mtk_crtc->pending_needs_vblank) { + mtk_crtc_finish_page_flip(mtk_crtc); + mtk_crtc->pending_needs_vblank = false; + } ++ spin_unlock_irqrestore(&mtk_crtc->config_lock, flags); + } + + #if IS_REACHABLE(CONFIG_MTK_CMDQ) +@@ -308,12 +315,19 @@ static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg) + struct mtk_crtc *mtk_crtc = container_of(cmdq_cl, struct mtk_crtc, cmdq_client); + struct mtk_crtc_state *state; + unsigned int i; ++ unsigned long flags; + + if (data->sta < 0) + return; + + state = to_mtk_crtc_state(mtk_crtc->base.state); + ++ spin_lock_irqsave(&mtk_crtc->config_lock, flags); ++ if (mtk_crtc->config_updating) { ++ spin_unlock_irqrestore(&mtk_crtc->config_lock, flags); ++ goto ddp_cmdq_cb_out; ++ } ++ + state->pending_config = false; + + if (mtk_crtc->pending_planes) { +@@ -340,6 +354,10 @@ static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg) + mtk_crtc->pending_async_planes = false; + } + ++ spin_unlock_irqrestore(&mtk_crtc->config_lock, flags); ++ ++ddp_cmdq_cb_out: ++ + mtk_crtc->cmdq_vblank_cnt = 0; + wake_up(&mtk_crtc->cb_blocking_queue); + } +@@ -449,6 +467,7 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_crtc *mtk_crtc) + { + struct drm_device *drm = mtk_crtc->base.dev; + struct drm_crtc *crtc = &mtk_crtc->base; ++ unsigned long flags; + int i; + + for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) { +@@ -480,10 +499,10 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_crtc *mtk_crtc) + pm_runtime_put(drm->dev); + + if (crtc->state->event && !crtc->state->active) { +- spin_lock_irq(&crtc->dev->event_lock); ++ spin_lock_irqsave(&crtc->dev->event_lock, flags); + drm_crtc_send_vblank_event(crtc, crtc->state->event); + crtc->state->event = NULL; +- spin_unlock_irq(&crtc->dev->event_lock); ++ spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + } + } + +@@ -569,9 +588,14 @@ static void mtk_crtc_update_config(struct mtk_crtc *mtk_crtc, bool needs_vblank) + struct mtk_drm_private *priv = crtc->dev->dev_private; + unsigned int pending_planes = 0, pending_async_planes = 0; + int i; ++ unsigned long flags; + + mutex_lock(&mtk_crtc->hw_lock); ++ ++ spin_lock_irqsave(&mtk_crtc->config_lock, flags); + mtk_crtc->config_updating = true; ++ spin_unlock_irqrestore(&mtk_crtc->config_lock, flags); ++ + if (needs_vblank) + mtk_crtc->pending_needs_vblank = true; + +@@ -625,7 +649,10 @@ static void mtk_crtc_update_config(struct mtk_crtc *mtk_crtc, bool needs_vblank) + mbox_client_txdone(mtk_crtc->cmdq_client.chan, 0); + } + #endif ++ spin_lock_irqsave(&mtk_crtc->config_lock, flags); + mtk_crtc->config_updating = false; ++ spin_unlock_irqrestore(&mtk_crtc->config_lock, flags); ++ + mutex_unlock(&mtk_crtc->hw_lock); + } + +@@ -1068,6 +1095,7 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path, + drm_mode_crtc_set_gamma_size(&mtk_crtc->base, gamma_lut_size); + drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, has_ctm, gamma_lut_size); + mutex_init(&mtk_crtc->hw_lock); ++ spin_lock_init(&mtk_crtc->config_lock); + + #if IS_REACHABLE(CONFIG_MTK_CMDQ) + i = priv->mbox_index++; +diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +index c003f970189b06..0eb3db9c3d9e61 100644 +--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c ++++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +@@ -65,6 +65,8 @@ void a5xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring, + + static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit) + { ++ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); ++ struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); + struct msm_ringbuffer *ring = submit->ring; + struct drm_gem_object *obj; + uint32_t *ptr, dwords; +@@ -109,6 +111,7 @@ static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit + } + } + ++ a5xx_gpu->last_seqno[ring->id] = submit->seqno; + a5xx_flush(gpu, ring, true); + a5xx_preempt_trigger(gpu); + +@@ -150,9 +153,13 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) + OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1); + OUT_RING(ring, 1); + +- /* Enable local preemption for finegrain preemption */ ++ /* ++ * Disable local preemption by default because it requires ++ * user-space to be aware of it and provide additional handling ++ * to restore rendering state or do various flushes on switch. ++ */ + OUT_PKT7(ring, CP_PREEMPT_ENABLE_LOCAL, 1); +- OUT_RING(ring, 0x1); ++ OUT_RING(ring, 0x0); + + /* Allow CP_CONTEXT_SWITCH_YIELD packets in the IB2 */ + OUT_PKT7(ring, CP_YIELD_ENABLE, 1); +@@ -206,6 +213,7 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) + /* Write the fence to the scratch register */ + OUT_PKT4(ring, REG_A5XX_CP_SCRATCH_REG(2), 1); + OUT_RING(ring, submit->seqno); ++ a5xx_gpu->last_seqno[ring->id] = submit->seqno; + + /* + * Execute a CACHE_FLUSH_TS event. This will ensure that the +diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.h b/drivers/gpu/drm/msm/adreno/a5xx_gpu.h +index c7187bcc5e9082..9c0d701fe4b85b 100644 +--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.h ++++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.h +@@ -34,8 +34,10 @@ struct a5xx_gpu { + struct drm_gem_object *preempt_counters_bo[MSM_GPU_MAX_RINGS]; + struct a5xx_preempt_record *preempt[MSM_GPU_MAX_RINGS]; + uint64_t preempt_iova[MSM_GPU_MAX_RINGS]; ++ uint32_t last_seqno[MSM_GPU_MAX_RINGS]; + + atomic_t preempt_state; ++ spinlock_t preempt_start_lock; + struct timer_list preempt_timer; + + struct drm_gem_object *shadow_bo; +diff --git a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c +index f58dd564d122ba..0469fea5501083 100644 +--- a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c ++++ b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c +@@ -55,6 +55,8 @@ static inline void update_wptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) + /* Return the highest priority ringbuffer with something in it */ + static struct msm_ringbuffer *get_next_ring(struct msm_gpu *gpu) + { ++ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); ++ struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); + unsigned long flags; + int i; + +@@ -64,6 +66,8 @@ static struct msm_ringbuffer *get_next_ring(struct msm_gpu *gpu) + + spin_lock_irqsave(&ring->preempt_lock, flags); + empty = (get_wptr(ring) == gpu->funcs->get_rptr(gpu, ring)); ++ if (!empty && ring == a5xx_gpu->cur_ring) ++ empty = ring->memptrs->fence == a5xx_gpu->last_seqno[i]; + spin_unlock_irqrestore(&ring->preempt_lock, flags); + + if (!empty) +@@ -97,12 +101,19 @@ void a5xx_preempt_trigger(struct msm_gpu *gpu) + if (gpu->nr_rings == 1) + return; + ++ /* ++ * Serialize preemption start to ensure that we always make ++ * decision on latest state. Otherwise we can get stuck in ++ * lower priority or empty ring. ++ */ ++ spin_lock_irqsave(&a5xx_gpu->preempt_start_lock, flags); ++ + /* + * Try to start preemption by moving from NONE to START. If + * unsuccessful, a preemption is already in flight + */ + if (!try_preempt_state(a5xx_gpu, PREEMPT_NONE, PREEMPT_START)) +- return; ++ goto out; + + /* Get the next ring to preempt to */ + ring = get_next_ring(gpu); +@@ -127,9 +138,11 @@ void a5xx_preempt_trigger(struct msm_gpu *gpu) + set_preempt_state(a5xx_gpu, PREEMPT_ABORT); + update_wptr(gpu, a5xx_gpu->cur_ring); + set_preempt_state(a5xx_gpu, PREEMPT_NONE); +- return; ++ goto out; + } + ++ spin_unlock_irqrestore(&a5xx_gpu->preempt_start_lock, flags); ++ + /* Make sure the wptr doesn't update while we're in motion */ + spin_lock_irqsave(&ring->preempt_lock, flags); + a5xx_gpu->preempt[ring->id]->wptr = get_wptr(ring); +@@ -152,6 +165,10 @@ void a5xx_preempt_trigger(struct msm_gpu *gpu) + + /* And actually start the preemption */ + gpu_write(gpu, REG_A5XX_CP_CONTEXT_SWITCH_CNTL, 1); ++ return; ++ ++out: ++ spin_unlock_irqrestore(&a5xx_gpu->preempt_start_lock, flags); + } + + void a5xx_preempt_irq(struct msm_gpu *gpu) +@@ -188,6 +205,12 @@ void a5xx_preempt_irq(struct msm_gpu *gpu) + update_wptr(gpu, a5xx_gpu->cur_ring); + + set_preempt_state(a5xx_gpu, PREEMPT_NONE); ++ ++ /* ++ * Try to trigger preemption again in case there was a submit or ++ * retire during ring switch ++ */ ++ a5xx_preempt_trigger(gpu); + } + + void a5xx_preempt_hw_init(struct msm_gpu *gpu) +@@ -204,6 +227,8 @@ void a5xx_preempt_hw_init(struct msm_gpu *gpu) + return; + + for (i = 0; i < gpu->nr_rings; i++) { ++ a5xx_gpu->preempt[i]->data = 0; ++ a5xx_gpu->preempt[i]->info = 0; + a5xx_gpu->preempt[i]->wptr = 0; + a5xx_gpu->preempt[i]->rptr = 0; + a5xx_gpu->preempt[i]->rbase = gpu->rb[i]->iova; +@@ -298,5 +323,6 @@ void a5xx_preempt_init(struct msm_gpu *gpu) + } + } + ++ spin_lock_init(&a5xx_gpu->preempt_start_lock); + timer_setup(&a5xx_gpu->preempt_timer, a5xx_preempt_timer, 0); + } +diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +index 789a11416f7a45..0fcae53c0b140b 100644 +--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c ++++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +@@ -388,18 +388,18 @@ static void a7xx_get_debugbus_blocks(struct msm_gpu *gpu, + const u32 *debugbus_blocks, *gbif_debugbus_blocks; + int i; + +- if (adreno_is_a730(adreno_gpu)) { ++ if (adreno_gpu->info->family == ADRENO_7XX_GEN1) { + debugbus_blocks = gen7_0_0_debugbus_blocks; + debugbus_blocks_count = ARRAY_SIZE(gen7_0_0_debugbus_blocks); + gbif_debugbus_blocks = a7xx_gbif_debugbus_blocks; + gbif_debugbus_blocks_count = ARRAY_SIZE(a7xx_gbif_debugbus_blocks); +- } else if (adreno_is_a740_family(adreno_gpu)) { ++ } else if (adreno_gpu->info->family == ADRENO_7XX_GEN2) { + debugbus_blocks = gen7_2_0_debugbus_blocks; + debugbus_blocks_count = ARRAY_SIZE(gen7_2_0_debugbus_blocks); + gbif_debugbus_blocks = a7xx_gbif_debugbus_blocks; + gbif_debugbus_blocks_count = ARRAY_SIZE(a7xx_gbif_debugbus_blocks); + } else { +- BUG_ON(!adreno_is_a750(adreno_gpu)); ++ BUG_ON(adreno_gpu->info->family != ADRENO_7XX_GEN3); + debugbus_blocks = gen7_9_0_debugbus_blocks; + debugbus_blocks_count = ARRAY_SIZE(gen7_9_0_debugbus_blocks); + gbif_debugbus_blocks = gen7_9_0_gbif_debugbus_blocks; +@@ -509,7 +509,7 @@ static void a6xx_get_debugbus(struct msm_gpu *gpu, + const struct a6xx_debugbus_block *cx_debugbus_blocks; + + if (adreno_is_a7xx(adreno_gpu)) { +- BUG_ON(!(adreno_is_a730(adreno_gpu) || adreno_is_a740_family(adreno_gpu))); ++ BUG_ON(adreno_gpu->info->family > ADRENO_7XX_GEN3); + cx_debugbus_blocks = a7xx_cx_debugbus_blocks; + nr_cx_debugbus_blocks = ARRAY_SIZE(a7xx_cx_debugbus_blocks); + } else { +@@ -660,13 +660,16 @@ static void a7xx_get_dbgahb_clusters(struct msm_gpu *gpu, + const struct gen7_sptp_cluster_registers *dbgahb_clusters; + unsigned dbgahb_clusters_size; + +- if (adreno_is_a730(adreno_gpu)) { ++ if (adreno_gpu->info->family == ADRENO_7XX_GEN1) { + dbgahb_clusters = gen7_0_0_sptp_clusters; + dbgahb_clusters_size = ARRAY_SIZE(gen7_0_0_sptp_clusters); +- } else { +- BUG_ON(!adreno_is_a740_family(adreno_gpu)); ++ } else if (adreno_gpu->info->family == ADRENO_7XX_GEN2) { + dbgahb_clusters = gen7_2_0_sptp_clusters; + dbgahb_clusters_size = ARRAY_SIZE(gen7_2_0_sptp_clusters); ++ } else { ++ BUG_ON(adreno_gpu->info->family != ADRENO_7XX_GEN3); ++ dbgahb_clusters = gen7_9_0_sptp_clusters; ++ dbgahb_clusters_size = ARRAY_SIZE(gen7_9_0_sptp_clusters); + } + + a6xx_state->dbgahb_clusters = state_kcalloc(a6xx_state, +@@ -818,14 +821,14 @@ static void a7xx_get_clusters(struct msm_gpu *gpu, + const struct gen7_cluster_registers *clusters; + unsigned clusters_size; + +- if (adreno_is_a730(adreno_gpu)) { ++ if (adreno_gpu->info->family == ADRENO_7XX_GEN1) { + clusters = gen7_0_0_clusters; + clusters_size = ARRAY_SIZE(gen7_0_0_clusters); +- } else if (adreno_is_a740_family(adreno_gpu)) { ++ } else if (adreno_gpu->info->family == ADRENO_7XX_GEN2) { + clusters = gen7_2_0_clusters; + clusters_size = ARRAY_SIZE(gen7_2_0_clusters); + } else { +- BUG_ON(!adreno_is_a750(adreno_gpu)); ++ BUG_ON(adreno_gpu->info->family != ADRENO_7XX_GEN3); + clusters = gen7_9_0_clusters; + clusters_size = ARRAY_SIZE(gen7_9_0_clusters); + } +@@ -893,7 +896,7 @@ static void a7xx_get_shader_block(struct msm_gpu *gpu, + if (WARN_ON(datasize > A6XX_CD_DATA_SIZE)) + return; + +- if (adreno_is_a730(adreno_gpu)) { ++ if (adreno_gpu->info->family == ADRENO_7XX_GEN1) { + gpu_rmw(gpu, REG_A7XX_SP_DBG_CNTL, GENMASK(1, 0), 3); + } + +@@ -923,7 +926,7 @@ static void a7xx_get_shader_block(struct msm_gpu *gpu, + datasize); + + out: +- if (adreno_is_a730(adreno_gpu)) { ++ if (adreno_gpu->info->family == ADRENO_7XX_GEN1) { + gpu_rmw(gpu, REG_A7XX_SP_DBG_CNTL, GENMASK(1, 0), 0); + } + } +@@ -956,14 +959,14 @@ static void a7xx_get_shaders(struct msm_gpu *gpu, + unsigned num_shader_blocks; + int i; + +- if (adreno_is_a730(adreno_gpu)) { ++ if (adreno_gpu->info->family == ADRENO_7XX_GEN1) { + shader_blocks = gen7_0_0_shader_blocks; + num_shader_blocks = ARRAY_SIZE(gen7_0_0_shader_blocks); +- } else if (adreno_is_a740_family(adreno_gpu)) { ++ } else if (adreno_gpu->info->family == ADRENO_7XX_GEN2) { + shader_blocks = gen7_2_0_shader_blocks; + num_shader_blocks = ARRAY_SIZE(gen7_2_0_shader_blocks); + } else { +- BUG_ON(!adreno_is_a750(adreno_gpu)); ++ BUG_ON(adreno_gpu->info->family != ADRENO_7XX_GEN3); + shader_blocks = gen7_9_0_shader_blocks; + num_shader_blocks = ARRAY_SIZE(gen7_9_0_shader_blocks); + } +@@ -1348,14 +1351,14 @@ static void a7xx_get_registers(struct msm_gpu *gpu, + const u32 *pre_crashdumper_regs; + const struct gen7_reg_list *reglist; + +- if (adreno_is_a730(adreno_gpu)) { ++ if (adreno_gpu->info->family == ADRENO_7XX_GEN1) { + reglist = gen7_0_0_reg_list; + pre_crashdumper_regs = gen7_0_0_pre_crashdumper_gpu_registers; +- } else if (adreno_is_a740_family(adreno_gpu)) { ++ } else if (adreno_gpu->info->family == ADRENO_7XX_GEN2) { + reglist = gen7_2_0_reg_list; + pre_crashdumper_regs = gen7_0_0_pre_crashdumper_gpu_registers; + } else { +- BUG_ON(!adreno_is_a750(adreno_gpu)); ++ BUG_ON(adreno_gpu->info->family != ADRENO_7XX_GEN3); + reglist = gen7_9_0_reg_list; + pre_crashdumper_regs = gen7_9_0_pre_crashdumper_gpu_registers; + } +@@ -1405,8 +1408,7 @@ static void a7xx_get_post_crashdumper_registers(struct msm_gpu *gpu, + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + const u32 *regs; + +- BUG_ON(!(adreno_is_a730(adreno_gpu) || adreno_is_a740_family(adreno_gpu) || +- adreno_is_a750(adreno_gpu))); ++ BUG_ON(adreno_gpu->info->family > ADRENO_7XX_GEN3); + regs = gen7_0_0_post_crashdumper_registers; + + a7xx_get_ahb_gpu_registers(gpu, +@@ -1514,11 +1516,11 @@ static void a7xx_get_indexed_registers(struct msm_gpu *gpu, + const struct a6xx_indexed_registers *indexed_regs; + int i, indexed_count, mempool_count; + +- if (adreno_is_a730(adreno_gpu) || adreno_is_a740_family(adreno_gpu)) { ++ if (adreno_gpu->info->family <= ADRENO_7XX_GEN2) { + indexed_regs = a7xx_indexed_reglist; + indexed_count = ARRAY_SIZE(a7xx_indexed_reglist); + } else { +- BUG_ON(!adreno_is_a750(adreno_gpu)); ++ BUG_ON(adreno_gpu->info->family != ADRENO_7XX_GEN3); + indexed_regs = gen7_9_0_cp_indexed_reg_list; + indexed_count = ARRAY_SIZE(gen7_9_0_cp_indexed_reg_list); + } +diff --git a/drivers/gpu/drm/msm/adreno/adreno_gen7_9_0_snapshot.h b/drivers/gpu/drm/msm/adreno/adreno_gen7_9_0_snapshot.h +index 260d66eccfecbf..9a327d543f27de 100644 +--- a/drivers/gpu/drm/msm/adreno/adreno_gen7_9_0_snapshot.h ++++ b/drivers/gpu/drm/msm/adreno/adreno_gen7_9_0_snapshot.h +@@ -1303,7 +1303,7 @@ static struct a6xx_indexed_registers gen7_9_0_cp_indexed_reg_list[] = { + REG_A6XX_CP_ROQ_DBG_DATA, 0x00800}, + { "CP_UCODE_DBG_DATA", REG_A6XX_CP_SQE_UCODE_DBG_ADDR, + REG_A6XX_CP_SQE_UCODE_DBG_DATA, 0x08000}, +- { "CP_BV_SQE_STAT_ADDR", REG_A7XX_CP_BV_DRAW_STATE_ADDR, ++ { "CP_BV_DRAW_STATE_ADDR", REG_A7XX_CP_BV_DRAW_STATE_ADDR, + REG_A7XX_CP_BV_DRAW_STATE_DATA, 0x00200}, + { "CP_BV_ROQ_DBG_ADDR", REG_A7XX_CP_BV_ROQ_DBG_ADDR, + REG_A7XX_CP_BV_ROQ_DBG_DATA, 0x00800}, +diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c +index b93ed15f04a30e..d5d9361e11aa53 100644 +--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c ++++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c +@@ -475,7 +475,7 @@ adreno_request_fw(struct adreno_gpu *adreno_gpu, const char *fwname) + ret = request_firmware_direct(&fw, fwname, drm->dev); + if (!ret) { + DRM_DEV_INFO(drm->dev, "loaded %s from legacy location\n", +- newname); ++ fwname); + adreno_gpu->fwloc = FW_LOCATION_LEGACY; + goto out; + } else if (adreno_gpu->fwloc != FW_LOCATION_UNKNOWN) { +diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c +index 3a7f7edda96b27..500b7dc895d055 100644 +--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c ++++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c +@@ -351,7 +351,7 @@ void mdp5_smp_dump(struct mdp5_smp *smp, struct drm_printer *p, + + drm_printf(p, "%s:%d\t%d\t%s\n", + pipe2name(pipe), j, inuse, +- plane ? plane->name : NULL); ++ plane ? plane->name : "(null)"); + + total += inuse; + } +diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c +index 672a7ba52edadd..9dc44ea85b7c62 100644 +--- a/drivers/gpu/drm/msm/dp/dp_display.c ++++ b/drivers/gpu/drm/msm/dp/dp_display.c +@@ -119,7 +119,7 @@ struct msm_dp_desc { + }; + + static const struct msm_dp_desc sc7180_dp_descs[] = { +- { .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0 }, ++ { .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true }, + {} + }; + +@@ -130,9 +130,9 @@ static const struct msm_dp_desc sc7280_dp_descs[] = { + }; + + static const struct msm_dp_desc sc8180x_dp_descs[] = { +- { .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0 }, +- { .io_start = 0x0ae98000, .id = MSM_DP_CONTROLLER_1 }, +- { .io_start = 0x0ae9a000, .id = MSM_DP_CONTROLLER_2 }, ++ { .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true }, ++ { .io_start = 0x0ae98000, .id = MSM_DP_CONTROLLER_1, .wide_bus_supported = true }, ++ { .io_start = 0x0ae9a000, .id = MSM_DP_CONTROLLER_2, .wide_bus_supported = true }, + {} + }; + +@@ -149,7 +149,7 @@ static const struct msm_dp_desc sc8280xp_dp_descs[] = { + }; + + static const struct msm_dp_desc sm8650_dp_descs[] = { +- { .io_start = 0x0af54000, .id = MSM_DP_CONTROLLER_0 }, ++ { .io_start = 0x0af54000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true }, + {} + }; + +diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +index 82d015aa2d634c..29aa91238bc47e 100644 +--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c ++++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +@@ -135,7 +135,7 @@ static void dsi_pll_calc_dec_frac(struct dsi_pll_7nm *pll, struct dsi_pll_config + config->pll_clock_inverters = 0x00; + else + config->pll_clock_inverters = 0x40; +- } else { ++ } else if (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1) { + if (pll_freq <= 1000000000ULL) + config->pll_clock_inverters = 0xa0; + else if (pll_freq <= 2500000000ULL) +@@ -144,6 +144,16 @@ static void dsi_pll_calc_dec_frac(struct dsi_pll_7nm *pll, struct dsi_pll_config + config->pll_clock_inverters = 0x00; + else + config->pll_clock_inverters = 0x40; ++ } else { ++ /* 4.2, 4.3 */ ++ if (pll_freq <= 1000000000ULL) ++ config->pll_clock_inverters = 0xa0; ++ else if (pll_freq <= 2500000000ULL) ++ config->pll_clock_inverters = 0x20; ++ else if (pll_freq <= 3500000000ULL) ++ config->pll_clock_inverters = 0x00; ++ else ++ config->pll_clock_inverters = 0x40; + } + + config->decimal_div_start = dec; +diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c +index 1fe6e0d883c79b..675a649fa7ab5d 100644 +--- a/drivers/gpu/drm/radeon/evergreen_cs.c ++++ b/drivers/gpu/drm/radeon/evergreen_cs.c +@@ -395,7 +395,7 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i + struct evergreen_cs_track *track = p->track; + struct eg_surface surf; + unsigned pitch, slice, mslice; +- unsigned long offset; ++ u64 offset; + int r; + + mslice = G_028C6C_SLICE_MAX(track->cb_color_view[id]) + 1; +@@ -433,14 +433,14 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i + return r; + } + +- offset = track->cb_color_bo_offset[id] << 8; ++ offset = (u64)track->cb_color_bo_offset[id] << 8; + if (offset & (surf.base_align - 1)) { +- dev_warn(p->dev, "%s:%d cb[%d] bo base %ld not aligned with %ld\n", ++ dev_warn(p->dev, "%s:%d cb[%d] bo base %llu not aligned with %ld\n", + __func__, __LINE__, id, offset, surf.base_align); + return -EINVAL; + } + +- offset += surf.layer_size * mslice; ++ offset += (u64)surf.layer_size * mslice; + if (offset > radeon_bo_size(track->cb_color_bo[id])) { + /* old ddx are broken they allocate bo with w*h*bpp but + * program slice with ALIGN(h, 8), catch this and patch +@@ -448,14 +448,14 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i + */ + if (!surf.mode) { + uint32_t *ib = p->ib.ptr; +- unsigned long tmp, nby, bsize, size, min = 0; ++ u64 tmp, nby, bsize, size, min = 0; + + /* find the height the ddx wants */ + if (surf.nby > 8) { + min = surf.nby - 8; + } + bsize = radeon_bo_size(track->cb_color_bo[id]); +- tmp = track->cb_color_bo_offset[id] << 8; ++ tmp = (u64)track->cb_color_bo_offset[id] << 8; + for (nby = surf.nby; nby > min; nby--) { + size = nby * surf.nbx * surf.bpe * surf.nsamples; + if ((tmp + size * mslice) <= bsize) { +@@ -467,7 +467,7 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i + slice = ((nby * surf.nbx) / 64) - 1; + if (!evergreen_surface_check(p, &surf, "cb")) { + /* check if this one works */ +- tmp += surf.layer_size * mslice; ++ tmp += (u64)surf.layer_size * mslice; + if (tmp <= bsize) { + ib[track->cb_color_slice_idx[id]] = slice; + goto old_ddx_ok; +@@ -476,9 +476,9 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i + } + } + dev_warn(p->dev, "%s:%d cb[%d] bo too small (layer size %d, " +- "offset %d, max layer %d, bo size %ld, slice %d)\n", ++ "offset %llu, max layer %d, bo size %ld, slice %d)\n", + __func__, __LINE__, id, surf.layer_size, +- track->cb_color_bo_offset[id] << 8, mslice, ++ (u64)track->cb_color_bo_offset[id] << 8, mslice, + radeon_bo_size(track->cb_color_bo[id]), slice); + dev_warn(p->dev, "%s:%d problematic surf: (%d %d) (%d %d %d %d %d %d %d)\n", + __func__, __LINE__, surf.nbx, surf.nby, +@@ -562,7 +562,7 @@ static int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p) + struct evergreen_cs_track *track = p->track; + struct eg_surface surf; + unsigned pitch, slice, mslice; +- unsigned long offset; ++ u64 offset; + int r; + + mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1; +@@ -608,18 +608,18 @@ static int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p) + return r; + } + +- offset = track->db_s_read_offset << 8; ++ offset = (u64)track->db_s_read_offset << 8; + if (offset & (surf.base_align - 1)) { +- dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n", ++ dev_warn(p->dev, "%s:%d stencil read bo base %llu not aligned with %ld\n", + __func__, __LINE__, offset, surf.base_align); + return -EINVAL; + } +- offset += surf.layer_size * mslice; ++ offset += (u64)surf.layer_size * mslice; + if (offset > radeon_bo_size(track->db_s_read_bo)) { + dev_warn(p->dev, "%s:%d stencil read bo too small (layer size %d, " +- "offset %ld, max layer %d, bo size %ld)\n", ++ "offset %llu, max layer %d, bo size %ld)\n", + __func__, __LINE__, surf.layer_size, +- (unsigned long)track->db_s_read_offset << 8, mslice, ++ (u64)track->db_s_read_offset << 8, mslice, + radeon_bo_size(track->db_s_read_bo)); + dev_warn(p->dev, "%s:%d stencil invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n", + __func__, __LINE__, track->db_depth_size, +@@ -627,18 +627,18 @@ static int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p) + return -EINVAL; + } + +- offset = track->db_s_write_offset << 8; ++ offset = (u64)track->db_s_write_offset << 8; + if (offset & (surf.base_align - 1)) { +- dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n", ++ dev_warn(p->dev, "%s:%d stencil write bo base %llu not aligned with %ld\n", + __func__, __LINE__, offset, surf.base_align); + return -EINVAL; + } +- offset += surf.layer_size * mslice; ++ offset += (u64)surf.layer_size * mslice; + if (offset > radeon_bo_size(track->db_s_write_bo)) { + dev_warn(p->dev, "%s:%d stencil write bo too small (layer size %d, " +- "offset %ld, max layer %d, bo size %ld)\n", ++ "offset %llu, max layer %d, bo size %ld)\n", + __func__, __LINE__, surf.layer_size, +- (unsigned long)track->db_s_write_offset << 8, mslice, ++ (u64)track->db_s_write_offset << 8, mslice, + radeon_bo_size(track->db_s_write_bo)); + return -EINVAL; + } +@@ -659,7 +659,7 @@ static int evergreen_cs_track_validate_depth(struct radeon_cs_parser *p) + struct evergreen_cs_track *track = p->track; + struct eg_surface surf; + unsigned pitch, slice, mslice; +- unsigned long offset; ++ u64 offset; + int r; + + mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1; +@@ -706,34 +706,34 @@ static int evergreen_cs_track_validate_depth(struct radeon_cs_parser *p) + return r; + } + +- offset = track->db_z_read_offset << 8; ++ offset = (u64)track->db_z_read_offset << 8; + if (offset & (surf.base_align - 1)) { +- dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n", ++ dev_warn(p->dev, "%s:%d stencil read bo base %llu not aligned with %ld\n", + __func__, __LINE__, offset, surf.base_align); + return -EINVAL; + } +- offset += surf.layer_size * mslice; ++ offset += (u64)surf.layer_size * mslice; + if (offset > radeon_bo_size(track->db_z_read_bo)) { + dev_warn(p->dev, "%s:%d depth read bo too small (layer size %d, " +- "offset %ld, max layer %d, bo size %ld)\n", ++ "offset %llu, max layer %d, bo size %ld)\n", + __func__, __LINE__, surf.layer_size, +- (unsigned long)track->db_z_read_offset << 8, mslice, ++ (u64)track->db_z_read_offset << 8, mslice, + radeon_bo_size(track->db_z_read_bo)); + return -EINVAL; + } + +- offset = track->db_z_write_offset << 8; ++ offset = (u64)track->db_z_write_offset << 8; + if (offset & (surf.base_align - 1)) { +- dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n", ++ dev_warn(p->dev, "%s:%d stencil write bo base %llu not aligned with %ld\n", + __func__, __LINE__, offset, surf.base_align); + return -EINVAL; + } +- offset += surf.layer_size * mslice; ++ offset += (u64)surf.layer_size * mslice; + if (offset > radeon_bo_size(track->db_z_write_bo)) { + dev_warn(p->dev, "%s:%d depth write bo too small (layer size %d, " +- "offset %ld, max layer %d, bo size %ld)\n", ++ "offset %llu, max layer %d, bo size %ld)\n", + __func__, __LINE__, surf.layer_size, +- (unsigned long)track->db_z_write_offset << 8, mslice, ++ (u64)track->db_z_write_offset << 8, mslice, + radeon_bo_size(track->db_z_write_bo)); + return -EINVAL; + } +diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c +index 10793a433bf586..d698a899eaf4cf 100644 +--- a/drivers/gpu/drm/radeon/radeon_atombios.c ++++ b/drivers/gpu/drm/radeon/radeon_atombios.c +@@ -1717,26 +1717,29 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct + fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record; + if (fake_edid_record->ucFakeEDIDLength) { + struct edid *edid; +- int edid_size = +- max((int)EDID_LENGTH, (int)fake_edid_record->ucFakeEDIDLength); +- edid = kmalloc(edid_size, GFP_KERNEL); ++ int edid_size; ++ ++ if (fake_edid_record->ucFakeEDIDLength == 128) ++ edid_size = fake_edid_record->ucFakeEDIDLength; ++ else ++ edid_size = fake_edid_record->ucFakeEDIDLength * 128; ++ edid = kmemdup(&fake_edid_record->ucFakeEDIDString[0], ++ edid_size, GFP_KERNEL); + if (edid) { +- memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0], +- fake_edid_record->ucFakeEDIDLength); +- + if (drm_edid_is_valid(edid)) { + rdev->mode_info.bios_hardcoded_edid = edid; + rdev->mode_info.bios_hardcoded_edid_size = edid_size; +- } else ++ } else { + kfree(edid); ++ } + } ++ record += struct_size(fake_edid_record, ++ ucFakeEDIDString, ++ edid_size); ++ } else { ++ /* empty fake edid record must be 3 bytes long */ ++ record += sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + 1; + } +- record += fake_edid_record->ucFakeEDIDLength ? +- struct_size(fake_edid_record, +- ucFakeEDIDString, +- fake_edid_record->ucFakeEDIDLength) : +- /* empty fake edid record must be 3 bytes long */ +- sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + 1; + break; + case LCD_PANEL_RESOLUTION_RECORD_TYPE: + panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record; +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index fe33092abbe7d7..aae48e906af11b 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -434,6 +434,8 @@ static void dw_hdmi_rk3328_setup_hpd(struct dw_hdmi *dw_hdmi, void *data) + HIWORD_UPDATE(RK3328_HDMI_SDAIN_MSK | RK3328_HDMI_SCLIN_MSK, + RK3328_HDMI_SDAIN_MSK | RK3328_HDMI_SCLIN_MSK | + RK3328_HDMI_HPD_IOE)); ++ ++ dw_hdmi_rk3328_read_hpd(dw_hdmi, data); + } + + static const struct dw_hdmi_phy_ops rk3228_hdmi_phy_ops = { +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index a13473b2d54c40..4a9c6ea7f15dc3 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -396,8 +396,8 @@ static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win, + if (info->is_yuv) + is_yuv = true; + +- if (dst_w > 3840) { +- DRM_DEV_ERROR(vop->dev, "Maximum dst width (3840) exceeded\n"); ++ if (dst_w > 4096) { ++ DRM_DEV_ERROR(vop->dev, "Maximum dst width (4096) exceeded\n"); + return; + } + +diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c +index e8523abef27a50..4d2db079ad4ff3 100644 +--- a/drivers/gpu/drm/stm/drv.c ++++ b/drivers/gpu/drm/stm/drv.c +@@ -203,12 +203,14 @@ static int stm_drm_platform_probe(struct platform_device *pdev) + + ret = drm_dev_register(ddev, 0); + if (ret) +- goto err_put; ++ goto err_unload; + + drm_fbdev_dma_setup(ddev, 16); + + return 0; + ++err_unload: ++ drv_unload(ddev); + err_put: + drm_dev_put(ddev); + +diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c +index 5576fdae496233..5aec1e58c968c2 100644 +--- a/drivers/gpu/drm/stm/ltdc.c ++++ b/drivers/gpu/drm/stm/ltdc.c +@@ -1580,6 +1580,8 @@ static struct drm_plane *ltdc_plane_create(struct drm_device *ddev, + ARRAY_SIZE(ltdc_drm_fmt_ycbcr_sp) + + ARRAY_SIZE(ltdc_drm_fmt_ycbcr_fp)) * + sizeof(*formats), GFP_KERNEL); ++ if (!formats) ++ return NULL; + + for (i = 0; i < ldev->caps.pix_fmt_nb; i++) { + drm_fmt = ldev->caps.pix_fmt_drm[i]; +diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c +index d30f8e8e896717..c75bd5af2cefd5 100644 +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -462,6 +462,7 @@ static int vc4_hdmi_connector_detect_ctx(struct drm_connector *connector, + { + struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); + enum drm_connector_status status = connector_status_disconnected; ++ int ret; + + /* + * NOTE: This function should really take vc4_hdmi->mutex, but +@@ -474,7 +475,12 @@ static int vc4_hdmi_connector_detect_ctx(struct drm_connector *connector, + * the lock for now. + */ + +- WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev)); ++ ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); ++ if (ret) { ++ drm_err_once(connector->dev, "Failed to retain HDMI power domain: %d\n", ++ ret); ++ return connector_status_unknown; ++ } + + if (vc4_hdmi->hpd_gpio) { + if (gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio)) +diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c +index d84740be96426a..7660f62e6c1f23 100644 +--- a/drivers/hid/wacom_wac.c ++++ b/drivers/hid/wacom_wac.c +@@ -2368,6 +2368,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, + wacom_map_usage(input, usage, field, EV_KEY, BTN_STYLUS3, 0); + features->quirks &= ~WACOM_QUIRK_PEN_BUTTON3; + break; ++ case WACOM_HID_WD_SEQUENCENUMBER: ++ wacom_wac->hid_data.sequence_number = -1; ++ break; + } + } + +@@ -2492,9 +2495,15 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field + wacom_wac->hid_data.barrelswitch3 = value; + return; + case WACOM_HID_WD_SEQUENCENUMBER: +- if (wacom_wac->hid_data.sequence_number != value) +- hid_warn(hdev, "Dropped %hu packets", (unsigned short)(value - wacom_wac->hid_data.sequence_number)); ++ if (wacom_wac->hid_data.sequence_number != value && ++ wacom_wac->hid_data.sequence_number >= 0) { ++ int sequence_size = field->logical_maximum - field->logical_minimum + 1; ++ int drop_count = (value - wacom_wac->hid_data.sequence_number) % sequence_size; ++ hid_warn(hdev, "Dropped %d packets", drop_count); ++ } + wacom_wac->hid_data.sequence_number = value + 1; ++ if (wacom_wac->hid_data.sequence_number > field->logical_maximum) ++ wacom_wac->hid_data.sequence_number = field->logical_minimum; + return; + } + +diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h +index 6ec499841f7095..e6443740b462fd 100644 +--- a/drivers/hid/wacom_wac.h ++++ b/drivers/hid/wacom_wac.h +@@ -324,7 +324,7 @@ struct hid_data { + int bat_connected; + int ps_connected; + bool pad_input_event_flag; +- unsigned short sequence_number; ++ int sequence_number; + ktime_t time_delayed; + }; + +diff --git a/drivers/hwmon/max16065.c b/drivers/hwmon/max16065.c +index aa38c45adc09e2..0ccb5eb596fc40 100644 +--- a/drivers/hwmon/max16065.c ++++ b/drivers/hwmon/max16065.c +@@ -79,7 +79,7 @@ static const bool max16065_have_current[] = { + }; + + struct max16065_data { +- enum chips type; ++ enum chips chip; + struct i2c_client *client; + const struct attribute_group *groups[4]; + struct mutex update_lock; +@@ -114,9 +114,10 @@ static inline int LIMIT_TO_MV(int limit, int range) + return limit * range / 256; + } + +-static inline int MV_TO_LIMIT(int mv, int range) ++static inline int MV_TO_LIMIT(unsigned long mv, int range) + { +- return clamp_val(DIV_ROUND_CLOSEST(mv * 256, range), 0, 255); ++ mv = clamp_val(mv, 0, ULONG_MAX / 256); ++ return DIV_ROUND_CLOSEST(clamp_val(mv * 256, 0, range * 255), range); + } + + static inline int ADC_TO_CURR(int adc, int gain) +@@ -161,10 +162,17 @@ static struct max16065_data *max16065_update_device(struct device *dev) + MAX16065_CURR_SENSE); + } + +- for (i = 0; i < DIV_ROUND_UP(data->num_adc, 8); i++) ++ for (i = 0; i < 2; i++) + data->fault[i] + = i2c_smbus_read_byte_data(client, MAX16065_FAULT(i)); + ++ /* ++ * MAX16067 and MAX16068 have separate undervoltage and ++ * overvoltage alarm bits. Squash them together. ++ */ ++ if (data->chip == max16067 || data->chip == max16068) ++ data->fault[0] |= data->fault[1]; ++ + data->last_updated = jiffies; + data->valid = true; + } +@@ -493,8 +501,6 @@ static const struct attribute_group max16065_max_group = { + .is_visible = max16065_secondary_is_visible, + }; + +-static const struct i2c_device_id max16065_id[]; +- + static int max16065_probe(struct i2c_client *client) + { + struct i2c_adapter *adapter = client->adapter; +@@ -505,7 +511,7 @@ static int max16065_probe(struct i2c_client *client) + bool have_secondary; /* true if chip has secondary limits */ + bool secondary_is_max = false; /* secondary limits reflect max */ + int groups = 0; +- const struct i2c_device_id *id = i2c_match_id(max16065_id, client); ++ enum chips chip = (uintptr_t)i2c_get_match_data(client); + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA + | I2C_FUNC_SMBUS_READ_WORD_DATA)) +@@ -515,12 +521,13 @@ static int max16065_probe(struct i2c_client *client) + if (unlikely(!data)) + return -ENOMEM; + ++ data->chip = chip; + data->client = client; + mutex_init(&data->update_lock); + +- data->num_adc = max16065_num_adc[id->driver_data]; +- data->have_current = max16065_have_current[id->driver_data]; +- have_secondary = max16065_have_secondary[id->driver_data]; ++ data->num_adc = max16065_num_adc[chip]; ++ data->have_current = max16065_have_current[chip]; ++ have_secondary = max16065_have_secondary[chip]; + + if (have_secondary) { + val = i2c_smbus_read_byte_data(client, MAX16065_SW_ENABLE); +diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c +index ef75b63f5894e5..b5352900463fb9 100644 +--- a/drivers/hwmon/ntc_thermistor.c ++++ b/drivers/hwmon/ntc_thermistor.c +@@ -62,6 +62,7 @@ static const struct platform_device_id ntc_thermistor_id[] = { + [NTC_SSG1404001221] = { "ssg1404_001221", TYPE_NCPXXWB473 }, + [NTC_LAST] = { }, + }; ++MODULE_DEVICE_TABLE(platform, ntc_thermistor_id); + + /* + * A compensation table should be sorted by the values of .ohm +diff --git a/drivers/hwtracing/coresight/coresight-dummy.c b/drivers/hwtracing/coresight/coresight-dummy.c +index ac70c0b491bebd..dab389a5507c11 100644 +--- a/drivers/hwtracing/coresight/coresight-dummy.c ++++ b/drivers/hwtracing/coresight/coresight-dummy.c +@@ -23,6 +23,9 @@ DEFINE_CORESIGHT_DEVLIST(sink_devs, "dummy_sink"); + static int dummy_source_enable(struct coresight_device *csdev, + struct perf_event *event, enum cs_mode mode) + { ++ if (!coresight_take_mode(csdev, mode)) ++ return -EBUSY; ++ + dev_dbg(csdev->dev.parent, "Dummy source enabled\n"); + + return 0; +@@ -31,6 +34,7 @@ static int dummy_source_enable(struct coresight_device *csdev, + static void dummy_source_disable(struct coresight_device *csdev, + struct perf_event *event) + { ++ coresight_set_mode(csdev, CS_MODE_DISABLED); + dev_dbg(csdev->dev.parent, "Dummy source disabled\n"); + } + +diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c +index e75428fa1592a7..610ad51cda656b 100644 +--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c ++++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c +@@ -261,6 +261,7 @@ void tmc_free_sg_table(struct tmc_sg_table *sg_table) + { + tmc_free_table_pages(sg_table); + tmc_free_data_pages(sg_table); ++ kfree(sg_table); + } + EXPORT_SYMBOL_GPL(tmc_free_sg_table); + +@@ -342,7 +343,6 @@ struct tmc_sg_table *tmc_alloc_sg_table(struct device *dev, + rc = tmc_alloc_table_pages(sg_table); + if (rc) { + tmc_free_sg_table(sg_table); +- kfree(sg_table); + return ERR_PTR(rc); + } + +diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c +index 0726f8842552c6..5c5a4b3fe6871c 100644 +--- a/drivers/hwtracing/coresight/coresight-tpdm.c ++++ b/drivers/hwtracing/coresight/coresight-tpdm.c +@@ -449,6 +449,11 @@ static int tpdm_enable(struct coresight_device *csdev, struct perf_event *event, + return -EBUSY; + } + ++ if (!coresight_take_mode(csdev, mode)) { ++ spin_unlock(&drvdata->spinlock); ++ return -EBUSY; ++ } ++ + __tpdm_enable(drvdata); + drvdata->enable = true; + spin_unlock(&drvdata->spinlock); +@@ -506,6 +511,7 @@ static void tpdm_disable(struct coresight_device *csdev, + } + + __tpdm_disable(drvdata); ++ coresight_set_mode(csdev, CS_MODE_DISABLED); + drvdata->enable = false; + spin_unlock(&drvdata->spinlock); + +diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c +index ce8c4846b7fae4..2a03a221e2dd57 100644 +--- a/drivers/i2c/busses/i2c-aspeed.c ++++ b/drivers/i2c/busses/i2c-aspeed.c +@@ -170,6 +170,13 @@ struct aspeed_i2c_bus { + + static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus); + ++/* precondition: bus.lock has been acquired. */ ++static void aspeed_i2c_do_stop(struct aspeed_i2c_bus *bus) ++{ ++ bus->master_state = ASPEED_I2C_MASTER_STOP; ++ writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG); ++} ++ + static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus) + { + unsigned long time_left, flags; +@@ -187,7 +194,7 @@ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus) + command); + + reinit_completion(&bus->cmd_complete); +- writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG); ++ aspeed_i2c_do_stop(bus); + spin_unlock_irqrestore(&bus->lock, flags); + + time_left = wait_for_completion_timeout( +@@ -390,13 +397,6 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus) + writel(command, bus->base + ASPEED_I2C_CMD_REG); + } + +-/* precondition: bus.lock has been acquired. */ +-static void aspeed_i2c_do_stop(struct aspeed_i2c_bus *bus) +-{ +- bus->master_state = ASPEED_I2C_MASTER_STOP; +- writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG); +-} +- + /* precondition: bus.lock has been acquired. */ + static void aspeed_i2c_next_msg_or_stop(struct aspeed_i2c_bus *bus) + { +diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c +index 416a9968ed2870..8b225412be5ba4 100644 +--- a/drivers/i2c/busses/i2c-isch.c ++++ b/drivers/i2c/busses/i2c-isch.c +@@ -99,8 +99,7 @@ static int sch_transaction(void) + if (retries > MAX_RETRIES) { + dev_err(&sch_adapter.dev, "SMBus Timeout!\n"); + result = -ETIMEDOUT; +- } +- if (temp & 0x04) { ++ } else if (temp & 0x04) { + result = -EIO; + dev_dbg(&sch_adapter.dev, "Bus collision! SMBus may be " + "locked until next hard reset. (sorry!)\n"); +diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c +index 1c08c0921ee712..4d755ffc3f4148 100644 +--- a/drivers/iio/adc/ad7606.c ++++ b/drivers/iio/adc/ad7606.c +@@ -215,9 +215,9 @@ static int ad7606_write_os_hw(struct iio_dev *indio_dev, int val) + struct ad7606_state *st = iio_priv(indio_dev); + DECLARE_BITMAP(values, 3); + +- values[0] = val; ++ values[0] = val & GENMASK(2, 0); + +- gpiod_set_array_value(ARRAY_SIZE(values), st->gpio_os->desc, ++ gpiod_set_array_value(st->gpio_os->ndescs, st->gpio_os->desc, + st->gpio_os->info, values); + + /* AD7616 requires a reset to update value */ +@@ -422,7 +422,7 @@ static int ad7606_request_gpios(struct ad7606_state *st) + return PTR_ERR(st->gpio_range); + + st->gpio_standby = devm_gpiod_get_optional(dev, "standby", +- GPIOD_OUT_HIGH); ++ GPIOD_OUT_LOW); + if (IS_ERR(st->gpio_standby)) + return PTR_ERR(st->gpio_standby); + +@@ -665,7 +665,7 @@ static int ad7606_suspend(struct device *dev) + + if (st->gpio_standby) { + gpiod_set_value(st->gpio_range, 1); +- gpiod_set_value(st->gpio_standby, 0); ++ gpiod_set_value(st->gpio_standby, 1); + } + + return 0; +diff --git a/drivers/iio/adc/ad7606_spi.c b/drivers/iio/adc/ad7606_spi.c +index 263a778bcf2539..287a0591533b6a 100644 +--- a/drivers/iio/adc/ad7606_spi.c ++++ b/drivers/iio/adc/ad7606_spi.c +@@ -249,8 +249,9 @@ static int ad7616_sw_mode_config(struct iio_dev *indio_dev) + static int ad7606B_sw_mode_config(struct iio_dev *indio_dev) + { + struct ad7606_state *st = iio_priv(indio_dev); +- unsigned long os[3] = {1}; ++ DECLARE_BITMAP(os, 3); + ++ bitmap_fill(os, 3); + /* + * Software mode is enabled when all three oversampling + * pins are set to high. If oversampling gpios are defined +@@ -258,7 +259,7 @@ static int ad7606B_sw_mode_config(struct iio_dev *indio_dev) + * otherwise, they must be hardwired to VDD + */ + if (st->gpio_os) { +- gpiod_set_array_value(ARRAY_SIZE(os), ++ gpiod_set_array_value(st->gpio_os->ndescs, + st->gpio_os->desc, st->gpio_os->info, os); + } + /* OS of 128 and 256 are available only in software mode */ +diff --git a/drivers/iio/chemical/bme680_core.c b/drivers/iio/chemical/bme680_core.c +index 500f56834b01f6..a6bf689833dad7 100644 +--- a/drivers/iio/chemical/bme680_core.c ++++ b/drivers/iio/chemical/bme680_core.c +@@ -10,6 +10,7 @@ + */ + #include <linux/acpi.h> + #include <linux/bitfield.h> ++#include <linux/cleanup.h> + #include <linux/delay.h> + #include <linux/device.h> + #include <linux/module.h> +@@ -52,6 +53,7 @@ struct bme680_calib { + struct bme680_data { + struct regmap *regmap; + struct bme680_calib bme680; ++ struct mutex lock; /* Protect multiple serial R/W ops to device. */ + u8 oversampling_temp; + u8 oversampling_press; + u8 oversampling_humid; +@@ -827,6 +829,8 @@ static int bme680_read_raw(struct iio_dev *indio_dev, + { + struct bme680_data *data = iio_priv(indio_dev); + ++ guard(mutex)(&data->lock); ++ + switch (mask) { + case IIO_CHAN_INFO_PROCESSED: + switch (chan->type) { +@@ -871,6 +875,8 @@ static int bme680_write_raw(struct iio_dev *indio_dev, + { + struct bme680_data *data = iio_priv(indio_dev); + ++ guard(mutex)(&data->lock); ++ + if (val2 != 0) + return -EINVAL; + +@@ -967,6 +973,7 @@ int bme680_core_probe(struct device *dev, struct regmap *regmap, + name = bme680_match_acpi_device(dev); + + data = iio_priv(indio_dev); ++ mutex_init(&data->lock); + dev_set_drvdata(dev, indio_dev); + data->regmap = regmap; + indio_dev->name = name; +diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c +index dd466c5fa6214f..ccbebe5b66cde2 100644 +--- a/drivers/iio/magnetometer/ak8975.c ++++ b/drivers/iio/magnetometer/ak8975.c +@@ -1081,7 +1081,6 @@ static const struct of_device_id ak8975_of_match[] = { + { .compatible = "asahi-kasei,ak09912", .data = &ak_def_array[AK09912] }, + { .compatible = "ak09912", .data = &ak_def_array[AK09912] }, + { .compatible = "asahi-kasei,ak09916", .data = &ak_def_array[AK09916] }, +- { .compatible = "ak09916", .data = &ak_def_array[AK09916] }, + {} + }; + MODULE_DEVICE_TABLE(of, ak8975_of_match); +diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c +index 6791df64a5fe05..b7c078b7f7cfd4 100644 +--- a/drivers/infiniband/core/cache.c ++++ b/drivers/infiniband/core/cache.c +@@ -1640,8 +1640,10 @@ int ib_cache_setup_one(struct ib_device *device) + + rdma_for_each_port (device, p) { + err = ib_cache_update(device, p, true, true, true); +- if (err) ++ if (err) { ++ gid_table_cleanup_one(device); + return err; ++ } + } + + return 0; +diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c +index bf3265e6786517..7d85fe41004240 100644 +--- a/drivers/infiniband/core/iwcm.c ++++ b/drivers/infiniband/core/iwcm.c +@@ -1190,7 +1190,7 @@ static int __init iw_cm_init(void) + if (ret) + return ret; + +- iwcm_wq = alloc_ordered_workqueue("iw_cm_wq", 0); ++ iwcm_wq = alloc_ordered_workqueue("iw_cm_wq", WQ_MEM_RECLAIM); + if (!iwcm_wq) + goto err_alloc; + +diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c +index 040ba2224f9ff6..b3757c6a0457a1 100644 +--- a/drivers/infiniband/hw/cxgb4/cm.c ++++ b/drivers/infiniband/hw/cxgb4/cm.c +@@ -1222,6 +1222,8 @@ static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb) + int ret; + + ep = lookup_atid(t, atid); ++ if (!ep) ++ return -EINVAL; + + pr_debug("ep %p tid %u snd_isn %u rcv_isn %u\n", ep, tid, + be32_to_cpu(req->snd_isn), be32_to_cpu(req->rcv_isn)); +@@ -2279,6 +2281,9 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb) + int ret = 0; + + ep = lookup_atid(t, atid); ++ if (!ep) ++ return -EINVAL; ++ + la = (struct sockaddr_in *)&ep->com.local_addr; + ra = (struct sockaddr_in *)&ep->com.remote_addr; + la6 = (struct sockaddr_in6 *)&ep->com.local_addr; +diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/infiniband/hw/erdma/erdma_verbs.c +index 40c9b6e46b82b3..3e3a3e1c241e79 100644 +--- a/drivers/infiniband/hw/erdma/erdma_verbs.c ++++ b/drivers/infiniband/hw/erdma/erdma_verbs.c +@@ -1544,11 +1544,31 @@ int erdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, + return ret; + } + ++static enum ib_qp_state query_qp_state(struct erdma_qp *qp) ++{ ++ switch (qp->attrs.state) { ++ case ERDMA_QP_STATE_IDLE: ++ return IB_QPS_INIT; ++ case ERDMA_QP_STATE_RTR: ++ return IB_QPS_RTR; ++ case ERDMA_QP_STATE_RTS: ++ return IB_QPS_RTS; ++ case ERDMA_QP_STATE_CLOSING: ++ return IB_QPS_ERR; ++ case ERDMA_QP_STATE_TERMINATE: ++ return IB_QPS_ERR; ++ case ERDMA_QP_STATE_ERROR: ++ return IB_QPS_ERR; ++ default: ++ return IB_QPS_ERR; ++ } ++} ++ + int erdma_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, + int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr) + { +- struct erdma_qp *qp; + struct erdma_dev *dev; ++ struct erdma_qp *qp; + + if (ibqp && qp_attr && qp_init_attr) { + qp = to_eqp(ibqp); +@@ -1575,6 +1595,9 @@ int erdma_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, + + qp_init_attr->cap = qp_attr->cap; + ++ qp_attr->qp_state = query_qp_state(qp); ++ qp_attr->cur_qp_state = query_qp_state(qp); ++ + return 0; + } + +diff --git a/drivers/infiniband/hw/hns/hns_roce_ah.c b/drivers/infiniband/hw/hns/hns_roce_ah.c +index 3e02c474f59fec..4fc5b9d5fea87e 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_ah.c ++++ b/drivers/infiniband/hw/hns/hns_roce_ah.c +@@ -64,8 +64,10 @@ int hns_roce_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr, + u8 tc_mode = 0; + int ret; + +- if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08 && udata) +- return -EOPNOTSUPP; ++ if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08 && udata) { ++ ret = -EOPNOTSUPP; ++ goto err_out; ++ } + + ah->av.port = rdma_ah_get_port_num(ah_attr); + ah->av.gid_index = grh->sgid_index; +@@ -83,7 +85,7 @@ int hns_roce_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr, + ret = 0; + + if (ret && grh->sgid_attr->gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP) +- return ret; ++ goto err_out; + + if (tc_mode == HNAE3_TC_MAP_MODE_DSCP && + grh->sgid_attr->gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP) +@@ -91,8 +93,10 @@ int hns_roce_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr, + else + ah->av.sl = rdma_ah_get_sl(ah_attr); + +- if (!check_sl_valid(hr_dev, ah->av.sl)) +- return -EINVAL; ++ if (!check_sl_valid(hr_dev, ah->av.sl)) { ++ ret = -EINVAL; ++ goto err_out; ++ } + + memcpy(ah->av.dgid, grh->dgid.raw, HNS_ROCE_GID_SIZE); + memcpy(ah->av.mac, ah_attr->roce.dmac, ETH_ALEN); +diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c +index 02baa853a76c9b..c7c167e2a04513 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hem.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hem.c +@@ -1041,9 +1041,9 @@ static bool hem_list_is_bottom_bt(int hopnum, int bt_level) + * @bt_level: base address table level + * @unit: ba entries per bt page + */ +-static u32 hem_list_calc_ba_range(int hopnum, int bt_level, int unit) ++static u64 hem_list_calc_ba_range(int hopnum, int bt_level, int unit) + { +- u32 step; ++ u64 step; + int max; + int i; + +@@ -1079,7 +1079,7 @@ int hns_roce_hem_list_calc_root_ba(const struct hns_roce_buf_region *regions, + { + struct hns_roce_buf_region *r; + int total = 0; +- int step; ++ u64 step; + int i; + + for (i = 0; i < region_cnt; i++) { +@@ -1110,7 +1110,7 @@ static int hem_list_alloc_mid_bt(struct hns_roce_dev *hr_dev, + int ret = 0; + int max_ofs; + int level; +- u32 step; ++ u64 step; + int end; + + if (hopnum <= 1) +@@ -1134,10 +1134,12 @@ static int hem_list_alloc_mid_bt(struct hns_roce_dev *hr_dev, + + /* config L1 bt to last bt and link them to corresponding parent */ + for (level = 1; level < hopnum; level++) { +- cur = hem_list_search_item(&mid_bt[level], offset); +- if (cur) { +- hem_ptrs[level] = cur; +- continue; ++ if (!hem_list_is_bottom_bt(hopnum, level)) { ++ cur = hem_list_search_item(&mid_bt[level], offset); ++ if (cur) { ++ hem_ptrs[level] = cur; ++ continue; ++ } + } + + step = hem_list_calc_ba_range(hopnum, level, unit); +@@ -1147,7 +1149,7 @@ static int hem_list_alloc_mid_bt(struct hns_roce_dev *hr_dev, + } + + start_aligned = (distance / step) * step + r->offset; +- end = min_t(int, start_aligned + step - 1, max_ofs); ++ end = min_t(u64, start_aligned + step - 1, max_ofs); + cur = hem_list_alloc_item(hr_dev, start_aligned, end, unit, + true); + if (!cur) { +@@ -1235,7 +1237,7 @@ static int setup_middle_bt(struct hns_roce_dev *hr_dev, void *cpu_base, + struct hns_roce_hem_item *hem, *temp_hem; + int total = 0; + int offset; +- int step; ++ u64 step; + + step = hem_list_calc_ba_range(r->hopnum, 1, unit); + if (step < 1) +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +index 621b057fb9daa6..24e906b9d3ae13 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +@@ -1681,8 +1681,8 @@ static int hns_roce_hw_v2_query_counter(struct hns_roce_dev *hr_dev, + + for (i = 0; i < HNS_ROCE_HW_CNT_TOTAL && i < *num_counters; i++) { + bd_idx = i / CNT_PER_DESC; +- if (!(desc[bd_idx].flag & HNS_ROCE_CMD_FLAG_NEXT) && +- bd_idx != HNS_ROCE_HW_CNT_TOTAL / CNT_PER_DESC) ++ if (bd_idx != HNS_ROCE_HW_CNT_TOTAL / CNT_PER_DESC && ++ !(desc[bd_idx].flag & cpu_to_le16(HNS_ROCE_CMD_FLAG_NEXT))) + break; + + cnt_data = (__le64 *)&desc[bd_idx].data[0]; +@@ -2972,6 +2972,9 @@ static int hns_roce_v2_init(struct hns_roce_dev *hr_dev) + + static void hns_roce_v2_exit(struct hns_roce_dev *hr_dev) + { ++ if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08) ++ free_mr_exit(hr_dev); ++ + hns_roce_function_clear(hr_dev); + + if (!hr_dev->is_vf) +@@ -4423,12 +4426,14 @@ static int config_qp_rq_buf(struct hns_roce_dev *hr_dev, + upper_32_bits(to_hr_hw_page_addr(mtts[0]))); + hr_reg_clear(qpc_mask, QPC_RQ_CUR_BLK_ADDR_H); + +- context->rq_nxt_blk_addr = cpu_to_le32(to_hr_hw_page_addr(mtts[1])); +- qpc_mask->rq_nxt_blk_addr = 0; +- +- hr_reg_write(context, QPC_RQ_NXT_BLK_ADDR_H, +- upper_32_bits(to_hr_hw_page_addr(mtts[1]))); +- hr_reg_clear(qpc_mask, QPC_RQ_NXT_BLK_ADDR_H); ++ if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08) { ++ context->rq_nxt_blk_addr = ++ cpu_to_le32(to_hr_hw_page_addr(mtts[1])); ++ qpc_mask->rq_nxt_blk_addr = 0; ++ hr_reg_write(context, QPC_RQ_NXT_BLK_ADDR_H, ++ upper_32_bits(to_hr_hw_page_addr(mtts[1]))); ++ hr_reg_clear(qpc_mask, QPC_RQ_NXT_BLK_ADDR_H); ++ } + + return 0; + } +@@ -6193,6 +6198,7 @@ static irqreturn_t abnormal_interrupt_basic(struct hns_roce_dev *hr_dev, + struct pci_dev *pdev = hr_dev->pci_dev; + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev); + const struct hnae3_ae_ops *ops = ae_dev->ops; ++ enum hnae3_reset_type reset_type; + irqreturn_t int_work = IRQ_NONE; + u32 int_en; + +@@ -6204,10 +6210,12 @@ static irqreturn_t abnormal_interrupt_basic(struct hns_roce_dev *hr_dev, + roce_write(hr_dev, ROCEE_VF_ABN_INT_ST_REG, + 1 << HNS_ROCE_V2_VF_INT_ST_AEQ_OVERFLOW_S); + ++ reset_type = hr_dev->is_vf ? ++ HNAE3_VF_FUNC_RESET : HNAE3_FUNC_RESET; ++ + /* Set reset level for reset_event() */ + if (ops->set_default_reset_request) +- ops->set_default_reset_request(ae_dev, +- HNAE3_FUNC_RESET); ++ ops->set_default_reset_request(ae_dev, reset_type); + if (ops->reset_event) + ops->reset_event(pdev, NULL); + +@@ -6277,7 +6285,7 @@ static u64 fmea_get_ram_res_addr(u32 res_type, __le64 *data) + res_type == ECC_RESOURCE_SCCC) + return le64_to_cpu(*data); + +- return le64_to_cpu(*data) << PAGE_SHIFT; ++ return le64_to_cpu(*data) << HNS_HW_PAGE_SHIFT; + } + + static int fmea_recover_others(struct hns_roce_dev *hr_dev, u32 res_type, +@@ -6949,9 +6957,6 @@ static void __hns_roce_hw_v2_uninit_instance(struct hnae3_handle *handle, + hr_dev->state = HNS_ROCE_DEVICE_STATE_UNINIT; + hns_roce_handle_device_err(hr_dev); + +- if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08) +- free_mr_exit(hr_dev); +- + hns_roce_exit(hr_dev); + kfree(hr_dev->priv); + ib_dealloc_device(&hr_dev->ib_dev); +diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c +index 1de384ce4d0e15..6b03ba671ff8f3 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_qp.c ++++ b/drivers/infiniband/hw/hns/hns_roce_qp.c +@@ -1460,19 +1460,19 @@ void hns_roce_lock_cqs(struct hns_roce_cq *send_cq, struct hns_roce_cq *recv_cq) + __acquire(&send_cq->lock); + __acquire(&recv_cq->lock); + } else if (unlikely(send_cq != NULL && recv_cq == NULL)) { +- spin_lock_irq(&send_cq->lock); ++ spin_lock(&send_cq->lock); + __acquire(&recv_cq->lock); + } else if (unlikely(send_cq == NULL && recv_cq != NULL)) { +- spin_lock_irq(&recv_cq->lock); ++ spin_lock(&recv_cq->lock); + __acquire(&send_cq->lock); + } else if (send_cq == recv_cq) { +- spin_lock_irq(&send_cq->lock); ++ spin_lock(&send_cq->lock); + __acquire(&recv_cq->lock); + } else if (send_cq->cqn < recv_cq->cqn) { +- spin_lock_irq(&send_cq->lock); ++ spin_lock(&send_cq->lock); + spin_lock_nested(&recv_cq->lock, SINGLE_DEPTH_NESTING); + } else { +- spin_lock_irq(&recv_cq->lock); ++ spin_lock(&recv_cq->lock); + spin_lock_nested(&send_cq->lock, SINGLE_DEPTH_NESTING); + } + } +@@ -1492,13 +1492,13 @@ void hns_roce_unlock_cqs(struct hns_roce_cq *send_cq, + spin_unlock(&recv_cq->lock); + } else if (send_cq == recv_cq) { + __release(&recv_cq->lock); +- spin_unlock_irq(&send_cq->lock); ++ spin_unlock(&send_cq->lock); + } else if (send_cq->cqn < recv_cq->cqn) { + spin_unlock(&recv_cq->lock); +- spin_unlock_irq(&send_cq->lock); ++ spin_unlock(&send_cq->lock); + } else { + spin_unlock(&send_cq->lock); +- spin_unlock_irq(&recv_cq->lock); ++ spin_unlock(&recv_cq->lock); + } + } + +diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c +index 12704efb7b19a8..954450195824c3 100644 +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -1347,7 +1347,7 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr, + if (attr->max_dest_rd_atomic > dev->hw_attrs.max_hw_ird) { + ibdev_err(&iwdev->ibdev, + "rd_atomic = %d, above max_hw_ird=%d\n", +- attr->max_rd_atomic, ++ attr->max_dest_rd_atomic, + dev->hw_attrs.max_hw_ird); + return -EINVAL; + } +diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c +index 43660c831b22cf..fdb0e62d805b9a 100644 +--- a/drivers/infiniband/hw/mlx5/main.c ++++ b/drivers/infiniband/hw/mlx5/main.c +@@ -542,7 +542,7 @@ static int mlx5_query_port_roce(struct ib_device *device, u32 port_num, + if (!ndev) + goto out; + +- if (dev->lag_active) { ++ if (mlx5_lag_is_roce(mdev) || mlx5_lag_is_sriov(mdev)) { + rcu_read_lock(); + upper = netdev_master_upper_dev_get_rcu(ndev); + if (upper) { +diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h +index f9abdca3493aa9..0b2f18c34ee5e6 100644 +--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h ++++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h +@@ -795,6 +795,7 @@ struct mlx5_cache_ent { + u8 is_tmp:1; + u8 disabled:1; + u8 fill_to_high_water:1; ++ u8 tmp_cleanup_scheduled:1; + + /* + * - limit is the low water mark for stored mkeys, 2* limit is the +@@ -826,7 +827,6 @@ struct mlx5_mkey_cache { + struct mutex rb_lock; + struct dentry *fs_root; + unsigned long last_add; +- struct delayed_work remove_ent_dwork; + }; + + struct mlx5_ib_port_resources { +diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c +index d3c1f63791a2b6..59bde614f061f5 100644 +--- a/drivers/infiniband/hw/mlx5/mr.c ++++ b/drivers/infiniband/hw/mlx5/mr.c +@@ -48,6 +48,7 @@ enum { + MAX_PENDING_REG_MR = 8, + }; + ++#define MLX5_MR_CACHE_PERSISTENT_ENTRY_MIN_DESCS 4 + #define MLX5_UMR_ALIGN 2048 + + static void +@@ -211,9 +212,9 @@ static void create_mkey_callback(int status, struct mlx5_async_work *context) + + spin_lock_irqsave(&ent->mkeys_queue.lock, flags); + push_mkey_locked(ent, mkey_out->mkey); ++ ent->pending--; + /* If we are doing fill_to_high_water then keep going. */ + queue_adjust_cache_locked(ent); +- ent->pending--; + spin_unlock_irqrestore(&ent->mkeys_queue.lock, flags); + kfree(mkey_out); + } +@@ -527,6 +528,21 @@ static void queue_adjust_cache_locked(struct mlx5_cache_ent *ent) + } + } + ++static void clean_keys(struct mlx5_ib_dev *dev, struct mlx5_cache_ent *ent) ++{ ++ u32 mkey; ++ ++ spin_lock_irq(&ent->mkeys_queue.lock); ++ while (ent->mkeys_queue.ci) { ++ mkey = pop_mkey_locked(ent); ++ spin_unlock_irq(&ent->mkeys_queue.lock); ++ mlx5_core_destroy_mkey(dev->mdev, mkey); ++ spin_lock_irq(&ent->mkeys_queue.lock); ++ } ++ ent->tmp_cleanup_scheduled = false; ++ spin_unlock_irq(&ent->mkeys_queue.lock); ++} ++ + static void __cache_work_func(struct mlx5_cache_ent *ent) + { + struct mlx5_ib_dev *dev = ent->dev; +@@ -598,7 +614,11 @@ static void delayed_cache_work_func(struct work_struct *work) + struct mlx5_cache_ent *ent; + + ent = container_of(work, struct mlx5_cache_ent, dwork.work); +- __cache_work_func(ent); ++ /* temp entries are never filled, only cleaned */ ++ if (ent->is_tmp) ++ clean_keys(ent->dev, ent); ++ else ++ __cache_work_func(ent); + } + + static int cache_ent_key_cmp(struct mlx5r_cache_rb_key key1, +@@ -659,6 +679,7 @@ mkey_cache_ent_from_rb_key(struct mlx5_ib_dev *dev, + { + struct rb_node *node = dev->cache.rb_root.rb_node; + struct mlx5_cache_ent *cur, *smallest = NULL; ++ u64 ndescs_limit; + int cmp; + + /* +@@ -677,10 +698,18 @@ mkey_cache_ent_from_rb_key(struct mlx5_ib_dev *dev, + return cur; + } + ++ /* ++ * Limit the usage of mkeys larger than twice the required size while ++ * also allowing the usage of smallest cache entry for small MRs. ++ */ ++ ndescs_limit = max_t(u64, rb_key.ndescs * 2, ++ MLX5_MR_CACHE_PERSISTENT_ENTRY_MIN_DESCS); ++ + return (smallest && + smallest->rb_key.access_mode == rb_key.access_mode && + smallest->rb_key.access_flags == rb_key.access_flags && +- smallest->rb_key.ats == rb_key.ats) ? ++ smallest->rb_key.ats == rb_key.ats && ++ smallest->rb_key.ndescs <= ndescs_limit) ? + smallest : + NULL; + } +@@ -765,21 +794,6 @@ struct mlx5_ib_mr *mlx5_mr_cache_alloc(struct mlx5_ib_dev *dev, + return _mlx5_mr_cache_alloc(dev, ent, access_flags); + } + +-static void clean_keys(struct mlx5_ib_dev *dev, struct mlx5_cache_ent *ent) +-{ +- u32 mkey; +- +- cancel_delayed_work(&ent->dwork); +- spin_lock_irq(&ent->mkeys_queue.lock); +- while (ent->mkeys_queue.ci) { +- mkey = pop_mkey_locked(ent); +- spin_unlock_irq(&ent->mkeys_queue.lock); +- mlx5_core_destroy_mkey(dev->mdev, mkey); +- spin_lock_irq(&ent->mkeys_queue.lock); +- } +- spin_unlock_irq(&ent->mkeys_queue.lock); +-} +- + static void mlx5_mkey_cache_debugfs_cleanup(struct mlx5_ib_dev *dev) + { + if (!mlx5_debugfs_root || dev->is_rep) +@@ -892,10 +906,6 @@ mlx5r_cache_create_ent_locked(struct mlx5_ib_dev *dev, + ent->limit = 0; + + mlx5_mkey_cache_debugfs_add_ent(dev, ent); +- } else { +- mod_delayed_work(ent->dev->cache.wq, +- &ent->dev->cache.remove_ent_dwork, +- msecs_to_jiffies(30 * 1000)); + } + + return ent; +@@ -906,35 +916,6 @@ mlx5r_cache_create_ent_locked(struct mlx5_ib_dev *dev, + return ERR_PTR(ret); + } + +-static void remove_ent_work_func(struct work_struct *work) +-{ +- struct mlx5_mkey_cache *cache; +- struct mlx5_cache_ent *ent; +- struct rb_node *cur; +- +- cache = container_of(work, struct mlx5_mkey_cache, +- remove_ent_dwork.work); +- mutex_lock(&cache->rb_lock); +- cur = rb_last(&cache->rb_root); +- while (cur) { +- ent = rb_entry(cur, struct mlx5_cache_ent, node); +- cur = rb_prev(cur); +- mutex_unlock(&cache->rb_lock); +- +- spin_lock_irq(&ent->mkeys_queue.lock); +- if (!ent->is_tmp) { +- spin_unlock_irq(&ent->mkeys_queue.lock); +- mutex_lock(&cache->rb_lock); +- continue; +- } +- spin_unlock_irq(&ent->mkeys_queue.lock); +- +- clean_keys(ent->dev, ent); +- mutex_lock(&cache->rb_lock); +- } +- mutex_unlock(&cache->rb_lock); +-} +- + int mlx5_mkey_cache_init(struct mlx5_ib_dev *dev) + { + struct mlx5_mkey_cache *cache = &dev->cache; +@@ -950,7 +931,6 @@ int mlx5_mkey_cache_init(struct mlx5_ib_dev *dev) + mutex_init(&dev->slow_path_mutex); + mutex_init(&dev->cache.rb_lock); + dev->cache.rb_root = RB_ROOT; +- INIT_DELAYED_WORK(&dev->cache.remove_ent_dwork, remove_ent_work_func); + cache->wq = alloc_ordered_workqueue("mkey_cache", WQ_MEM_RECLAIM); + if (!cache->wq) { + mlx5_ib_warn(dev, "failed to create work queue\n"); +@@ -962,7 +942,7 @@ int mlx5_mkey_cache_init(struct mlx5_ib_dev *dev) + mlx5_mkey_cache_debugfs_init(dev); + mutex_lock(&cache->rb_lock); + for (i = 0; i <= mkey_cache_max_order(dev); i++) { +- rb_key.ndescs = 1 << (i + 2); ++ rb_key.ndescs = MLX5_MR_CACHE_PERSISTENT_ENTRY_MIN_DESCS << i; + ent = mlx5r_cache_create_ent_locked(dev, rb_key, true); + if (IS_ERR(ent)) { + ret = PTR_ERR(ent); +@@ -1001,7 +981,6 @@ void mlx5_mkey_cache_cleanup(struct mlx5_ib_dev *dev) + return; + + mutex_lock(&dev->cache.rb_lock); +- cancel_delayed_work(&dev->cache.remove_ent_dwork); + for (node = rb_first(root); node; node = rb_next(node)) { + ent = rb_entry(node, struct mlx5_cache_ent, node); + spin_lock_irq(&ent->mkeys_queue.lock); +@@ -1843,8 +1822,18 @@ static int mlx5_revoke_mr(struct mlx5_ib_mr *mr) + struct mlx5_ib_dev *dev = to_mdev(mr->ibmr.device); + struct mlx5_cache_ent *ent = mr->mmkey.cache_ent; + +- if (mr->mmkey.cacheable && !mlx5r_umr_revoke_mr(mr) && !cache_ent_find_and_store(dev, mr)) ++ if (mr->mmkey.cacheable && !mlx5r_umr_revoke_mr(mr) && !cache_ent_find_and_store(dev, mr)) { ++ ent = mr->mmkey.cache_ent; ++ /* upon storing to a clean temp entry - schedule its cleanup */ ++ spin_lock_irq(&ent->mkeys_queue.lock); ++ if (ent->is_tmp && !ent->tmp_cleanup_scheduled) { ++ mod_delayed_work(ent->dev->cache.wq, &ent->dwork, ++ msecs_to_jiffies(30 * 1000)); ++ ent->tmp_cleanup_scheduled = true; ++ } ++ spin_unlock_irq(&ent->mkeys_queue.lock); + return 0; ++ } + + if (ent) { + spin_lock_irq(&ent->mkeys_queue.lock); +diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c +index 88106cf5ce550c..84d2dfcd20af6f 100644 +--- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c ++++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c +@@ -626,6 +626,7 @@ static void rtrs_clt_rdma_done(struct ib_cq *cq, struct ib_wc *wc) + */ + if (WARN_ON(wc->wr_cqe->done != rtrs_clt_rdma_done)) + return; ++ clt_path->s.hb_missed_cnt = 0; + rtrs_from_imm(be32_to_cpu(wc->ex.imm_data), + &imm_type, &imm_payload); + if (imm_type == RTRS_IO_RSP_IMM || +@@ -643,7 +644,6 @@ static void rtrs_clt_rdma_done(struct ib_cq *cq, struct ib_wc *wc) + return rtrs_clt_recv_done(con, wc); + } else if (imm_type == RTRS_HB_ACK_IMM) { + WARN_ON(con->c.cid); +- clt_path->s.hb_missed_cnt = 0; + clt_path->s.hb_cur_latency = + ktime_sub(ktime_get(), clt_path->s.hb_last_sent); + if (clt_path->flags & RTRS_MSG_NEW_RKEY_F) +@@ -670,6 +670,7 @@ static void rtrs_clt_rdma_done(struct ib_cq *cq, struct ib_wc *wc) + /* + * Key invalidations from server side + */ ++ clt_path->s.hb_missed_cnt = 0; + WARN_ON(!(wc->wc_flags & IB_WC_WITH_INVALIDATE || + wc->wc_flags & IB_WC_WITH_IMM)); + WARN_ON(wc->wr_cqe->done != rtrs_clt_rdma_done); +@@ -2346,6 +2347,12 @@ static int init_conns(struct rtrs_clt_path *clt_path) + if (err) + goto destroy; + } ++ ++ /* ++ * Set the cid to con_num - 1, since if we fail later, we want to stay in bounds. ++ */ ++ cid = clt_path->s.con_num - 1; ++ + err = alloc_path_reqs(clt_path); + if (err) + goto destroy; +diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c +index 1d33efb8fb03be..94ac99a4f696e7 100644 +--- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c ++++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c +@@ -1229,6 +1229,7 @@ static void rtrs_srv_rdma_done(struct ib_cq *cq, struct ib_wc *wc) + */ + if (WARN_ON(wc->wr_cqe != &io_comp_cqe)) + return; ++ srv_path->s.hb_missed_cnt = 0; + err = rtrs_post_recv_empty(&con->c, &io_comp_cqe); + if (err) { + rtrs_err(s, "rtrs_post_recv(), err: %d\n", err); +diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c +index 1b0279393df4bb..5acaffb7f6e11d 100644 +--- a/drivers/input/keyboard/adp5588-keys.c ++++ b/drivers/input/keyboard/adp5588-keys.c +@@ -627,7 +627,7 @@ static int adp5588_setup(struct adp5588_kpad *kpad) + + for (i = 0; i < KEYP_MAX_EVENT; i++) { + ret = adp5588_read(client, KEY_EVENTA); +- if (ret) ++ if (ret < 0) + return ret; + } + +diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h +index bad238f69a7afd..34d1f07ea4c304 100644 +--- a/drivers/input/serio/i8042-acpipnpio.h ++++ b/drivers/input/serio/i8042-acpipnpio.h +@@ -1120,6 +1120,43 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { + }, + .driver_data = (void *)(SERIO_QUIRK_NOLOOP) + }, ++ /* ++ * Some TongFang barebones have touchpad and/or keyboard issues after ++ * suspend fixable with nomux + reset + noloop + nopnp. Luckily, none of ++ * them have an external PS/2 port so this can safely be set for all of ++ * them. ++ * TongFang barebones come with board_vendor and/or system_vendor set to ++ * a different value for each individual reseller. The only somewhat ++ * universal way to identify them is by board_name. ++ */ ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_NAME, "GM6XGxX"), ++ }, ++ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | ++ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_NAME, "GMxXGxx"), ++ }, ++ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | ++ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_NAME, "GMxXGxX"), ++ }, ++ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | ++ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_NAME, "GMxHGxx"), ++ }, ++ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | ++ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) ++ }, + /* + * A lot of modern Clevo barebones have touchpad and/or keyboard issues + * after suspend fixable with nomux + reset + noloop + nopnp. Luckily, +diff --git a/drivers/input/touchscreen/ilitek_ts_i2c.c b/drivers/input/touchscreen/ilitek_ts_i2c.c +index 3eb762896345b7..5a807ad723190d 100644 +--- a/drivers/input/touchscreen/ilitek_ts_i2c.c ++++ b/drivers/input/touchscreen/ilitek_ts_i2c.c +@@ -37,6 +37,8 @@ + #define ILITEK_TP_CMD_GET_MCU_VER 0x61 + #define ILITEK_TP_CMD_GET_IC_MODE 0xC0 + ++#define ILITEK_TP_I2C_REPORT_ID 0x48 ++ + #define REPORT_COUNT_ADDRESS 61 + #define ILITEK_SUPPORT_MAX_POINT 40 + +@@ -160,15 +162,19 @@ static int ilitek_process_and_report_v6(struct ilitek_ts_data *ts) + error = ilitek_i2c_write_and_read(ts, NULL, 0, 0, buf, 64); + if (error) { + dev_err(dev, "get touch info failed, err:%d\n", error); +- goto err_sync_frame; ++ return error; ++ } ++ ++ if (buf[0] != ILITEK_TP_I2C_REPORT_ID) { ++ dev_err(dev, "get touch info failed. Wrong id: 0x%02X\n", buf[0]); ++ return -EINVAL; + } + + report_max_point = buf[REPORT_COUNT_ADDRESS]; + if (report_max_point > ts->max_tp) { + dev_err(dev, "FW report max point:%d > panel info. max:%d\n", + report_max_point, ts->max_tp); +- error = -EINVAL; +- goto err_sync_frame; ++ return -EINVAL; + } + + count = DIV_ROUND_UP(report_max_point, packet_max_point); +@@ -178,7 +184,7 @@ static int ilitek_process_and_report_v6(struct ilitek_ts_data *ts) + if (error) { + dev_err(dev, "get touch info. failed, cnt:%d, err:%d\n", + count, error); +- goto err_sync_frame; ++ return error; + } + } + +@@ -203,10 +209,10 @@ static int ilitek_process_and_report_v6(struct ilitek_ts_data *ts) + ilitek_touch_down(ts, id, x, y); + } + +-err_sync_frame: + input_mt_sync_frame(input); + input_sync(input); +- return error; ++ ++ return 0; + } + + /* APIs of cmds for ILITEK Touch IC */ +diff --git a/drivers/interconnect/icc-clk.c b/drivers/interconnect/icc-clk.c +index d787f2ea36d97b..a91df709cfb2f3 100644 +--- a/drivers/interconnect/icc-clk.c ++++ b/drivers/interconnect/icc-clk.c +@@ -87,6 +87,7 @@ struct icc_provider *icc_clk_register(struct device *dev, + onecell = devm_kzalloc(dev, struct_size(onecell, nodes, 2 * num_clocks), GFP_KERNEL); + if (!onecell) + return ERR_PTR(-ENOMEM); ++ onecell->num_nodes = 2 * num_clocks; + + qp = devm_kzalloc(dev, struct_size(qp, clocks, num_clocks), GFP_KERNEL); + if (!qp) +@@ -133,8 +134,6 @@ struct icc_provider *icc_clk_register(struct device *dev, + onecell->nodes[j++] = node; + } + +- onecell->num_nodes = j; +- + ret = icc_provider_register(provider); + if (ret) + goto err; +diff --git a/drivers/interconnect/qcom/sm8350.c b/drivers/interconnect/qcom/sm8350.c +index b321c3009acbac..885a9d3f92e4d1 100644 +--- a/drivers/interconnect/qcom/sm8350.c ++++ b/drivers/interconnect/qcom/sm8350.c +@@ -1965,6 +1965,7 @@ static struct platform_driver qnoc_driver = { + .driver = { + .name = "qnoc-sm8350", + .of_match_table = qnoc_of_match, ++ .sync_state = icc_sync_state, + }, + }; + module_platform_driver(qnoc_driver); +diff --git a/drivers/iommu/amd/io_pgtable.c b/drivers/iommu/amd/io_pgtable.c +index 9d9a7fde59e75d..05aed3cb46f1bf 100644 +--- a/drivers/iommu/amd/io_pgtable.c ++++ b/drivers/iommu/amd/io_pgtable.c +@@ -574,23 +574,27 @@ static void v1_free_pgtable(struct io_pgtable *iop) + pgtable->mode > PAGE_MODE_6_LEVEL); + + free_sub_pt(pgtable->root, pgtable->mode, &freelist); ++ iommu_put_pages_list(&freelist); + + /* Update data structure */ + amd_iommu_domain_clr_pt_root(dom); + + /* Make changes visible to IOMMUs */ + amd_iommu_domain_update(dom); +- +- iommu_put_pages_list(&freelist); + } + + static struct io_pgtable *v1_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie) + { + struct amd_io_pgtable *pgtable = io_pgtable_cfg_to_data(cfg); + +- cfg->pgsize_bitmap = AMD_IOMMU_PGSIZES, +- cfg->ias = IOMMU_IN_ADDR_BIT_SIZE, +- cfg->oas = IOMMU_OUT_ADDR_BIT_SIZE, ++ pgtable->root = iommu_alloc_page(GFP_KERNEL); ++ if (!pgtable->root) ++ return NULL; ++ pgtable->mode = PAGE_MODE_3_LEVEL; ++ ++ cfg->pgsize_bitmap = AMD_IOMMU_PGSIZES; ++ cfg->ias = IOMMU_IN_ADDR_BIT_SIZE; ++ cfg->oas = IOMMU_OUT_ADDR_BIT_SIZE; + cfg->tlb = &v1_flush_ops; + + pgtable->iop.ops.map_pages = iommu_v1_map_pages; +diff --git a/drivers/iommu/amd/io_pgtable_v2.c b/drivers/iommu/amd/io_pgtable_v2.c +index 78ac37c5ccc1e0..743f417b281d4b 100644 +--- a/drivers/iommu/amd/io_pgtable_v2.c ++++ b/drivers/iommu/amd/io_pgtable_v2.c +@@ -51,7 +51,7 @@ static inline u64 set_pgtable_attr(u64 *page) + u64 prot; + + prot = IOMMU_PAGE_PRESENT | IOMMU_PAGE_RW | IOMMU_PAGE_USER; +- prot |= IOMMU_PAGE_ACCESS | IOMMU_PAGE_DIRTY; ++ prot |= IOMMU_PAGE_ACCESS; + + return (iommu_virt_to_phys(page) | prot); + } +@@ -362,7 +362,7 @@ static struct io_pgtable *v2_alloc_pgtable(struct io_pgtable_cfg *cfg, void *coo + struct protection_domain *pdom = (struct protection_domain *)cookie; + int ias = IOMMU_IN_ADDR_BIT_SIZE; + +- pgtable->pgd = iommu_alloc_page_node(pdom->nid, GFP_ATOMIC); ++ pgtable->pgd = iommu_alloc_page_node(pdom->nid, GFP_KERNEL); + if (!pgtable->pgd) + return NULL; + +diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c +index b19e8c0f48fa25..1a61f14459e4fe 100644 +--- a/drivers/iommu/amd/iommu.c ++++ b/drivers/iommu/amd/iommu.c +@@ -52,8 +52,6 @@ + #define HT_RANGE_START (0xfd00000000ULL) + #define HT_RANGE_END (0xffffffffffULL) + +-#define DEFAULT_PGTABLE_LEVEL PAGE_MODE_3_LEVEL +- + static DEFINE_SPINLOCK(pd_bitmap_lock); + + LIST_HEAD(ioapic_map); +@@ -1552,8 +1550,8 @@ void amd_iommu_dev_flush_pasid_pages(struct iommu_dev_data *dev_data, + void amd_iommu_dev_flush_pasid_all(struct iommu_dev_data *dev_data, + ioasid_t pasid) + { +- amd_iommu_dev_flush_pasid_pages(dev_data, 0, +- CMD_INV_IOMMU_ALL_PAGES_ADDRESS, pasid); ++ amd_iommu_dev_flush_pasid_pages(dev_data, pasid, 0, ++ CMD_INV_IOMMU_ALL_PAGES_ADDRESS); + } + + void amd_iommu_domain_flush_complete(struct protection_domain *domain) +@@ -2185,11 +2183,12 @@ static struct iommu_device *amd_iommu_probe_device(struct device *dev) + dev_err(dev, "Failed to initialize - trying to proceed anyway\n"); + iommu_dev = ERR_PTR(ret); + iommu_ignore_device(iommu, dev); +- } else { +- amd_iommu_set_pci_msi_domain(dev, iommu); +- iommu_dev = &iommu->iommu; ++ goto out_err; + } + ++ amd_iommu_set_pci_msi_domain(dev, iommu); ++ iommu_dev = &iommu->iommu; ++ + /* + * If IOMMU and device supports PASID then it will contain max + * supported PASIDs, else it will be zero. +@@ -2201,6 +2200,7 @@ static struct iommu_device *amd_iommu_probe_device(struct device *dev) + pci_max_pasids(to_pci_dev(dev))); + } + ++out_err: + iommu_completion_wait(iommu); + + return iommu_dev; +@@ -2265,47 +2265,17 @@ void protection_domain_free(struct protection_domain *domain) + if (domain->iop.pgtbl_cfg.tlb) + free_io_pgtable_ops(&domain->iop.iop.ops); + +- if (domain->iop.root) +- iommu_free_page(domain->iop.root); +- + if (domain->id) + domain_id_free(domain->id); + + kfree(domain); + } + +-static int protection_domain_init_v1(struct protection_domain *domain, int mode) +-{ +- u64 *pt_root = NULL; +- +- BUG_ON(mode < PAGE_MODE_NONE || mode > PAGE_MODE_6_LEVEL); +- +- if (mode != PAGE_MODE_NONE) { +- pt_root = iommu_alloc_page(GFP_KERNEL); +- if (!pt_root) +- return -ENOMEM; +- } +- +- domain->pd_mode = PD_MODE_V1; +- amd_iommu_domain_set_pgtable(domain, pt_root, mode); +- +- return 0; +-} +- +-static int protection_domain_init_v2(struct protection_domain *pdom) +-{ +- pdom->pd_mode = PD_MODE_V2; +- pdom->domain.pgsize_bitmap = AMD_IOMMU_PGSIZES_V2; +- +- return 0; +-} +- + struct protection_domain *protection_domain_alloc(unsigned int type) + { + struct io_pgtable_ops *pgtbl_ops; + struct protection_domain *domain; + int pgtable; +- int ret; + + domain = kzalloc(sizeof(*domain), GFP_KERNEL); + if (!domain) +@@ -2341,18 +2311,14 @@ struct protection_domain *protection_domain_alloc(unsigned int type) + + switch (pgtable) { + case AMD_IOMMU_V1: +- ret = protection_domain_init_v1(domain, DEFAULT_PGTABLE_LEVEL); ++ domain->pd_mode = PD_MODE_V1; + break; + case AMD_IOMMU_V2: +- ret = protection_domain_init_v2(domain); ++ domain->pd_mode = PD_MODE_V2; + break; + default: +- ret = -EINVAL; +- break; +- } +- +- if (ret) + goto out_err; ++ } + + pgtbl_ops = alloc_io_pgtable_ops(pgtable, &domain->iop.pgtbl_cfg, domain); + if (!pgtbl_ops) +@@ -2405,10 +2371,10 @@ static struct iommu_domain *do_iommu_domain_alloc(unsigned int type, + domain->domain.geometry.aperture_start = 0; + domain->domain.geometry.aperture_end = dma_max_address(); + domain->domain.geometry.force_aperture = true; ++ domain->domain.pgsize_bitmap = domain->iop.iop.cfg.pgsize_bitmap; + + if (iommu) { + domain->domain.type = type; +- domain->domain.pgsize_bitmap = iommu->iommu.ops->pgsize_bitmap; + domain->domain.ops = iommu->iommu.ops->default_domain_ops; + + if (dirty_tracking) +@@ -2867,7 +2833,6 @@ const struct iommu_ops amd_iommu_ops = { + .device_group = amd_iommu_device_group, + .get_resv_regions = amd_iommu_get_resv_regions, + .is_attach_deferred = amd_iommu_is_attach_deferred, +- .pgsize_bitmap = AMD_IOMMU_PGSIZES, + .def_domain_type = amd_iommu_def_domain_type, + .dev_enable_feat = amd_iommu_dev_enable_feature, + .dev_disable_feat = amd_iommu_dev_disable_feature, +diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c +index 13f3e2efb2ccbf..ccca410c948164 100644 +--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c ++++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c +@@ -282,6 +282,20 @@ static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu) + u32 smr; + int i; + ++ /* ++ * MSM8998 LPASS SMMU reports 13 context banks, but accessing ++ * the last context bank crashes the system. ++ */ ++ if (of_device_is_compatible(smmu->dev->of_node, "qcom,msm8998-smmu-v2") && ++ smmu->num_context_banks == 13) { ++ smmu->num_context_banks = 12; ++ } else if (of_device_is_compatible(smmu->dev->of_node, "qcom,sdm630-smmu-v2")) { ++ if (smmu->num_context_banks == 21) /* SDM630 / SDM660 A2NOC SMMU */ ++ smmu->num_context_banks = 7; ++ else if (smmu->num_context_banks == 14) /* SDM630 / SDM660 LPASS SMMU */ ++ smmu->num_context_banks = 13; ++ } ++ + /* + * Some platforms support more than the Arm SMMU architected maximum of + * 128 stream matching groups. For unknown reasons, the additional +@@ -338,6 +352,19 @@ static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu) + return 0; + } + ++static int qcom_adreno_smmuv2_cfg_probe(struct arm_smmu_device *smmu) ++{ ++ /* Support for 16K pages is advertised on some SoCs, but it doesn't seem to work */ ++ smmu->features &= ~ARM_SMMU_FEAT_FMT_AARCH64_16K; ++ ++ /* TZ protects several last context banks, hide them from Linux */ ++ if (of_device_is_compatible(smmu->dev->of_node, "qcom,sdm630-smmu-v2") && ++ smmu->num_context_banks == 5) ++ smmu->num_context_banks = 2; ++ ++ return 0; ++} ++ + static void qcom_smmu_write_s2cr(struct arm_smmu_device *smmu, int idx) + { + struct arm_smmu_s2cr *s2cr = smmu->s2crs + idx; +@@ -436,6 +463,7 @@ static const struct arm_smmu_impl sdm845_smmu_500_impl = { + + static const struct arm_smmu_impl qcom_adreno_smmu_v2_impl = { + .init_context = qcom_adreno_smmu_init_context, ++ .cfg_probe = qcom_adreno_smmuv2_cfg_probe, + .def_domain_type = qcom_smmu_def_domain_type, + .alloc_context_bank = qcom_adreno_smmu_alloc_context_bank, + .write_sctlr = qcom_adreno_smmu_write_sctlr, +diff --git a/drivers/iommu/iommufd/hw_pagetable.c b/drivers/iommu/iommufd/hw_pagetable.c +index a9f1fe44c4c0bd..21f0d8cbd7aade 100644 +--- a/drivers/iommu/iommufd/hw_pagetable.c ++++ b/drivers/iommu/iommufd/hw_pagetable.c +@@ -215,7 +215,8 @@ iommufd_hwpt_nested_alloc(struct iommufd_ctx *ictx, + + if (flags || !user_data->len || !ops->domain_alloc_user) + return ERR_PTR(-EOPNOTSUPP); +- if (parent->auto_domain || !parent->nest_parent) ++ if (parent->auto_domain || !parent->nest_parent || ++ parent->common.domain->owner != ops) + return ERR_PTR(-EINVAL); + + hwpt_nested = __iommufd_object_alloc( +diff --git a/drivers/iommu/iommufd/io_pagetable.c b/drivers/iommu/iommufd/io_pagetable.c +index 05fd9d3abf1b80..9f193c933de6ef 100644 +--- a/drivers/iommu/iommufd/io_pagetable.c ++++ b/drivers/iommu/iommufd/io_pagetable.c +@@ -112,6 +112,7 @@ static int iopt_alloc_iova(struct io_pagetable *iopt, unsigned long *iova, + unsigned long page_offset = uptr % PAGE_SIZE; + struct interval_tree_double_span_iter used_span; + struct interval_tree_span_iter allowed_span; ++ unsigned long max_alignment = PAGE_SIZE; + unsigned long iova_alignment; + + lockdep_assert_held(&iopt->iova_rwsem); +@@ -131,6 +132,13 @@ static int iopt_alloc_iova(struct io_pagetable *iopt, unsigned long *iova, + roundup_pow_of_two(length), + 1UL << __ffs64(uptr)); + ++#ifdef CONFIG_TRANSPARENT_HUGEPAGE ++ max_alignment = HPAGE_SIZE; ++#endif ++ /* Protect against ALIGN() overflow */ ++ if (iova_alignment >= max_alignment) ++ iova_alignment = max_alignment; ++ + if (iova_alignment < iopt->iova_alignment) + return -EINVAL; + +diff --git a/drivers/iommu/iommufd/selftest.c b/drivers/iommu/iommufd/selftest.c +index 654ed333909579..62bfeb7a35d850 100644 +--- a/drivers/iommu/iommufd/selftest.c ++++ b/drivers/iommu/iommufd/selftest.c +@@ -1313,7 +1313,7 @@ static int iommufd_test_dirty(struct iommufd_ucmd *ucmd, unsigned int mockpt_id, + unsigned long page_size, void __user *uptr, + u32 flags) + { +- unsigned long bitmap_size, i, max; ++ unsigned long i, max; + struct iommu_test_cmd *cmd = ucmd->cmd; + struct iommufd_hw_pagetable *hwpt; + struct mock_iommu_domain *mock; +@@ -1334,15 +1334,14 @@ static int iommufd_test_dirty(struct iommufd_ucmd *ucmd, unsigned int mockpt_id, + } + + max = length / page_size; +- bitmap_size = DIV_ROUND_UP(max, BITS_PER_BYTE); +- +- tmp = kvzalloc(bitmap_size, GFP_KERNEL_ACCOUNT); ++ tmp = kvzalloc(DIV_ROUND_UP(max, BITS_PER_LONG) * sizeof(unsigned long), ++ GFP_KERNEL_ACCOUNT); + if (!tmp) { + rc = -ENOMEM; + goto out_put; + } + +- if (copy_from_user(tmp, uptr, bitmap_size)) { ++ if (copy_from_user(tmp, uptr,DIV_ROUND_UP(max, BITS_PER_BYTE))) { + rc = -EFAULT; + goto out_free; + } +diff --git a/drivers/leds/leds-bd2606mvv.c b/drivers/leds/leds-bd2606mvv.c +index 3fda712d2f8095..c1181a35d0f762 100644 +--- a/drivers/leds/leds-bd2606mvv.c ++++ b/drivers/leds/leds-bd2606mvv.c +@@ -69,16 +69,14 @@ static const struct regmap_config bd2606mvv_regmap = { + + static int bd2606mvv_probe(struct i2c_client *client) + { +- struct fwnode_handle *np, *child; + struct device *dev = &client->dev; + struct bd2606mvv_priv *priv; + struct fwnode_handle *led_fwnodes[BD2606_MAX_LEDS] = { 0 }; + int active_pairs[BD2606_MAX_LEDS / 2] = { 0 }; + int err, reg; +- int i; ++ int i, j; + +- np = dev_fwnode(dev); +- if (!np) ++ if (!dev_fwnode(dev)) + return -ENODEV; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); +@@ -94,20 +92,18 @@ static int bd2606mvv_probe(struct i2c_client *client) + + i2c_set_clientdata(client, priv); + +- fwnode_for_each_available_child_node(np, child) { ++ device_for_each_child_node_scoped(dev, child) { + struct bd2606mvv_led *led; + + err = fwnode_property_read_u32(child, "reg", ®); +- if (err) { +- fwnode_handle_put(child); ++ if (err) + return err; +- } +- if (reg < 0 || reg >= BD2606_MAX_LEDS || led_fwnodes[reg]) { +- fwnode_handle_put(child); ++ ++ if (reg < 0 || reg >= BD2606_MAX_LEDS || led_fwnodes[reg]) + return -EINVAL; +- } ++ + led = &priv->leds[reg]; +- led_fwnodes[reg] = child; ++ led_fwnodes[reg] = fwnode_handle_get(child); + active_pairs[reg / 2]++; + led->priv = priv; + led->led_no = reg; +@@ -130,7 +126,8 @@ static int bd2606mvv_probe(struct i2c_client *client) + &priv->leds[i].ldev, + &init_data); + if (err < 0) { +- fwnode_handle_put(child); ++ for (j = i; j < BD2606_MAX_LEDS; j++) ++ fwnode_handle_put(led_fwnodes[j]); + return dev_err_probe(dev, err, + "couldn't register LED %s\n", + priv->leds[i].ldev.name); +diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c +index 83fcd7b6afff76..4d1612d557c841 100644 +--- a/drivers/leds/leds-gpio.c ++++ b/drivers/leds/leds-gpio.c +@@ -150,7 +150,7 @@ static struct gpio_leds_priv *gpio_leds_create(struct device *dev) + { + struct fwnode_handle *child; + struct gpio_leds_priv *priv; +- int count, ret; ++ int count, used, ret; + + count = device_get_child_node_count(dev); + if (!count) +@@ -159,9 +159,11 @@ static struct gpio_leds_priv *gpio_leds_create(struct device *dev) + priv = devm_kzalloc(dev, struct_size(priv, leds, count), GFP_KERNEL); + if (!priv) + return ERR_PTR(-ENOMEM); ++ priv->num_leds = count; ++ used = 0; + + device_for_each_child_node(dev, child) { +- struct gpio_led_data *led_dat = &priv->leds[priv->num_leds]; ++ struct gpio_led_data *led_dat = &priv->leds[used]; + struct gpio_led led = {}; + + /* +@@ -197,8 +199,9 @@ static struct gpio_leds_priv *gpio_leds_create(struct device *dev) + /* Set gpiod label to match the corresponding LED name. */ + gpiod_set_consumer_name(led_dat->gpiod, + led_dat->cdev.dev->kobj.name); +- priv->num_leds++; ++ used++; + } ++ priv->num_leds = used; + + return priv; + } +diff --git a/drivers/leds/leds-pca995x.c b/drivers/leds/leds-pca995x.c +index 78215dff14997c..11c7bb69573e8c 100644 +--- a/drivers/leds/leds-pca995x.c ++++ b/drivers/leds/leds-pca995x.c +@@ -19,10 +19,6 @@ + #define PCA995X_MODE1 0x00 + #define PCA995X_MODE2 0x01 + #define PCA995X_LEDOUT0 0x02 +-#define PCA9955B_PWM0 0x08 +-#define PCA9952_PWM0 0x0A +-#define PCA9952_IREFALL 0x43 +-#define PCA9955B_IREFALL 0x45 + + /* Auto-increment disabled. Normal mode */ + #define PCA995X_MODE1_CFG 0x00 +@@ -34,17 +30,38 @@ + #define PCA995X_LDRX_MASK 0x3 + #define PCA995X_LDRX_BITS 2 + +-#define PCA995X_MAX_OUTPUTS 16 ++#define PCA995X_MAX_OUTPUTS 24 + #define PCA995X_OUTPUTS_PER_REG 4 + + #define PCA995X_IREFALL_FULL_CFG 0xFF + #define PCA995X_IREFALL_HALF_CFG (PCA995X_IREFALL_FULL_CFG / 2) + +-#define PCA995X_TYPE_NON_B 0 +-#define PCA995X_TYPE_B 1 +- + #define ldev_to_led(c) container_of(c, struct pca995x_led, ldev) + ++struct pca995x_chipdef { ++ unsigned int num_leds; ++ u8 pwm_base; ++ u8 irefall; ++}; ++ ++static const struct pca995x_chipdef pca9952_chipdef = { ++ .num_leds = 16, ++ .pwm_base = 0x0a, ++ .irefall = 0x43, ++}; ++ ++static const struct pca995x_chipdef pca9955b_chipdef = { ++ .num_leds = 16, ++ .pwm_base = 0x08, ++ .irefall = 0x45, ++}; ++ ++static const struct pca995x_chipdef pca9956b_chipdef = { ++ .num_leds = 24, ++ .pwm_base = 0x0a, ++ .irefall = 0x40, ++}; ++ + struct pca995x_led { + unsigned int led_no; + struct led_classdev ldev; +@@ -54,7 +71,7 @@ struct pca995x_led { + struct pca995x_chip { + struct regmap *regmap; + struct pca995x_led leds[PCA995X_MAX_OUTPUTS]; +- int btype; ++ const struct pca995x_chipdef *chipdef; + }; + + static int pca995x_brightness_set(struct led_classdev *led_cdev, +@@ -62,10 +79,11 @@ static int pca995x_brightness_set(struct led_classdev *led_cdev, + { + struct pca995x_led *led = ldev_to_led(led_cdev); + struct pca995x_chip *chip = led->chip; ++ const struct pca995x_chipdef *chipdef = chip->chipdef; + u8 ledout_addr, pwmout_addr; + int shift, ret; + +- pwmout_addr = (chip->btype ? PCA9955B_PWM0 : PCA9952_PWM0) + led->led_no; ++ pwmout_addr = chipdef->pwm_base + led->led_no; + ledout_addr = PCA995X_LEDOUT0 + (led->led_no / PCA995X_OUTPUTS_PER_REG); + shift = PCA995X_LDRX_BITS * (led->led_no % PCA995X_OUTPUTS_PER_REG); + +@@ -102,43 +120,38 @@ static const struct regmap_config pca995x_regmap = { + static int pca995x_probe(struct i2c_client *client) + { + struct fwnode_handle *led_fwnodes[PCA995X_MAX_OUTPUTS] = { 0 }; +- struct fwnode_handle *np, *child; + struct device *dev = &client->dev; ++ const struct pca995x_chipdef *chipdef; + struct pca995x_chip *chip; + struct pca995x_led *led; +- int i, btype, reg, ret; ++ int i, j, reg, ret; + +- btype = (unsigned long)device_get_match_data(&client->dev); ++ chipdef = device_get_match_data(&client->dev); + +- np = dev_fwnode(dev); +- if (!np) ++ if (!dev_fwnode(dev)) + return -ENODEV; + + chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + +- chip->btype = btype; ++ chip->chipdef = chipdef; + chip->regmap = devm_regmap_init_i2c(client, &pca995x_regmap); + if (IS_ERR(chip->regmap)) + return PTR_ERR(chip->regmap); + + i2c_set_clientdata(client, chip); + +- fwnode_for_each_available_child_node(np, child) { ++ device_for_each_child_node_scoped(dev, child) { + ret = fwnode_property_read_u32(child, "reg", ®); +- if (ret) { +- fwnode_handle_put(child); ++ if (ret) + return ret; +- } + +- if (reg < 0 || reg >= PCA995X_MAX_OUTPUTS || led_fwnodes[reg]) { +- fwnode_handle_put(child); ++ if (reg < 0 || reg >= PCA995X_MAX_OUTPUTS || led_fwnodes[reg]) + return -EINVAL; +- } + + led = &chip->leds[reg]; +- led_fwnodes[reg] = child; ++ led_fwnodes[reg] = fwnode_handle_get(child); + led->chip = chip; + led->led_no = reg; + led->ldev.brightness_set_blocking = pca995x_brightness_set; +@@ -157,7 +170,8 @@ static int pca995x_probe(struct i2c_client *client) + &chip->leds[i].ldev, + &init_data); + if (ret < 0) { +- fwnode_handle_put(child); ++ for (j = i; j < PCA995X_MAX_OUTPUTS; j++) ++ fwnode_handle_put(led_fwnodes[j]); + return dev_err_probe(dev, ret, + "Could not register LED %s\n", + chip->leds[i].ldev.name); +@@ -170,21 +184,21 @@ static int pca995x_probe(struct i2c_client *client) + return ret; + + /* IREF Output current value for all LEDn outputs */ +- return regmap_write(chip->regmap, +- btype ? PCA9955B_IREFALL : PCA9952_IREFALL, +- PCA995X_IREFALL_HALF_CFG); ++ return regmap_write(chip->regmap, chipdef->irefall, PCA995X_IREFALL_HALF_CFG); + } + + static const struct i2c_device_id pca995x_id[] = { +- { "pca9952", .driver_data = (kernel_ulong_t)PCA995X_TYPE_NON_B }, +- { "pca9955b", .driver_data = (kernel_ulong_t)PCA995X_TYPE_B }, ++ { "pca9952", .driver_data = (kernel_ulong_t)&pca9952_chipdef }, ++ { "pca9955b", .driver_data = (kernel_ulong_t)&pca9955b_chipdef }, ++ { "pca9956b", .driver_data = (kernel_ulong_t)&pca9956b_chipdef }, + {} + }; + MODULE_DEVICE_TABLE(i2c, pca995x_id); + + static const struct of_device_id pca995x_of_match[] = { +- { .compatible = "nxp,pca9952", .data = (void *)PCA995X_TYPE_NON_B }, +- { .compatible = "nxp,pca9955b", .data = (void *)PCA995X_TYPE_B }, ++ { .compatible = "nxp,pca9952", .data = &pca9952_chipdef }, ++ { .compatible = "nxp,pca9955b", . data = &pca9955b_chipdef }, ++ { .compatible = "nxp,pca9956b", .data = &pca9956b_chipdef }, + {}, + }; + MODULE_DEVICE_TABLE(of, pca995x_of_match); +diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c +index f7e9a3632eb3d9..499f8cc8a39fbf 100644 +--- a/drivers/md/dm-rq.c ++++ b/drivers/md/dm-rq.c +@@ -496,8 +496,10 @@ static blk_status_t dm_mq_queue_rq(struct blk_mq_hw_ctx *hctx, + + map = dm_get_live_table(md, &srcu_idx); + if (unlikely(!map)) { ++ DMERR_LIMIT("%s: mapping table unavailable, erroring io", ++ dm_device_name(md)); + dm_put_live_table(md, srcu_idx); +- return BLK_STS_RESOURCE; ++ return BLK_STS_IOERR; + } + ti = dm_table_find_target(map, 0); + dm_put_live_table(md, srcu_idx); +diff --git a/drivers/md/dm.c b/drivers/md/dm.c +index 6e15ac4e0845cd..a0b4afba8c608e 100644 +--- a/drivers/md/dm.c ++++ b/drivers/md/dm.c +@@ -1880,10 +1880,15 @@ static void dm_submit_bio(struct bio *bio) + struct dm_table *map; + + map = dm_get_live_table(md, &srcu_idx); ++ if (unlikely(!map)) { ++ DMERR_LIMIT("%s: mapping table unavailable, erroring io", ++ dm_device_name(md)); ++ bio_io_error(bio); ++ goto out; ++ } + +- /* If suspended, or map not yet available, queue this IO for later */ +- if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) || +- unlikely(!map)) { ++ /* If suspended, queue this IO for later */ ++ if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags))) { + if (bio->bi_opf & REQ_NOWAIT) + bio_wouldblock_error(bio); + else if (bio->bi_opf & REQ_RAHEAD) +diff --git a/drivers/md/md.c b/drivers/md/md.c +index a5b5801baa9e83..e832b8b5e631f2 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -8648,7 +8648,6 @@ void md_write_start(struct mddev *mddev, struct bio *bi) + BUG_ON(mddev->ro == MD_RDONLY); + if (mddev->ro == MD_AUTO_READ) { + /* need to switch to read/write */ +- flush_work(&mddev->sync_work); + mddev->ro = MD_RDWR; + set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + md_wakeup_thread(mddev->thread); +diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c +index 30d10fe4b33e34..320aa2bf99d423 100644 +--- a/drivers/media/dvb-frontends/rtl2830.c ++++ b/drivers/media/dvb-frontends/rtl2830.c +@@ -609,7 +609,7 @@ static int rtl2830_pid_filter(struct dvb_frontend *fe, u8 index, u16 pid, int on + index, pid, onoff); + + /* skip invalid PIDs (0x2000) */ +- if (pid > 0x1fff || index > 32) ++ if (pid > 0x1fff || index >= 32) + return 0; + + if (onoff) +diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c +index 5142820b1b3d97..76c3f40443b2c9 100644 +--- a/drivers/media/dvb-frontends/rtl2832.c ++++ b/drivers/media/dvb-frontends/rtl2832.c +@@ -983,7 +983,7 @@ static int rtl2832_pid_filter(struct dvb_frontend *fe, u8 index, u16 pid, + index, pid, onoff, dev->slave_ts); + + /* skip invalid PIDs (0x2000) */ +- if (pid > 0x1fff || index > 32) ++ if (pid > 0x1fff || index >= 32) + return 0; + + if (onoff) +diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_if.c +index 73d5cef33b2abf..1e1b32faac77bc 100644 +--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_if.c ++++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_if.c +@@ -347,11 +347,16 @@ static int vdec_h264_slice_decode(void *h_vdec, struct mtk_vcodec_mem *bs, + return vpu_dec_reset(vpu); + + fb = inst->ctx->dev->vdec_pdata->get_cap_buffer(inst->ctx); ++ if (!fb) { ++ mtk_vdec_err(inst->ctx, "fb buffer is NULL"); ++ return -ENOMEM; ++ } ++ + src_buf_info = container_of(bs, struct mtk_video_dec_buf, bs_buffer); + dst_buf_info = container_of(fb, struct mtk_video_dec_buf, frame_buffer); + +- y_fb_dma = fb ? (u64)fb->base_y.dma_addr : 0; +- c_fb_dma = fb ? (u64)fb->base_c.dma_addr : 0; ++ y_fb_dma = fb->base_y.dma_addr; ++ c_fb_dma = fb->base_c.dma_addr; + + mtk_vdec_debug(inst->ctx, "+ [%d] FB y_dma=%llx c_dma=%llx va=%p", + inst->num_nalu, y_fb_dma, c_fb_dma, fb); +diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c +index 2d4611e7fa0b2f..1ed0ccec56655e 100644 +--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c ++++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c +@@ -724,11 +724,16 @@ static int vdec_h264_slice_single_decode(void *h_vdec, struct mtk_vcodec_mem *bs + return vpu_dec_reset(vpu); + + fb = inst->ctx->dev->vdec_pdata->get_cap_buffer(inst->ctx); ++ if (!fb) { ++ mtk_vdec_err(inst->ctx, "fb buffer is NULL"); ++ return -ENOMEM; ++ } ++ + src_buf_info = container_of(bs, struct mtk_video_dec_buf, bs_buffer); + dst_buf_info = container_of(fb, struct mtk_video_dec_buf, frame_buffer); + +- y_fb_dma = fb ? (u64)fb->base_y.dma_addr : 0; +- c_fb_dma = fb ? (u64)fb->base_c.dma_addr : 0; ++ y_fb_dma = fb->base_y.dma_addr; ++ c_fb_dma = fb->base_c.dma_addr; + mtk_vdec_debug(inst->ctx, "[h264-dec] [%d] y_dma=%llx c_dma=%llx", + inst->ctx->decoded_frame_cnt, y_fb_dma, c_fb_dma); + +diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp8_req_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp8_req_if.c +index e27e728f392e6c..232ef3bd246a3d 100644 +--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp8_req_if.c ++++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp8_req_if.c +@@ -334,14 +334,18 @@ static int vdec_vp8_slice_decode(void *h_vdec, struct mtk_vcodec_mem *bs, + src_buf_info = container_of(bs, struct mtk_video_dec_buf, bs_buffer); + + fb = inst->ctx->dev->vdec_pdata->get_cap_buffer(inst->ctx); +- dst_buf_info = container_of(fb, struct mtk_video_dec_buf, frame_buffer); ++ if (!fb) { ++ mtk_vdec_err(inst->ctx, "fb buffer is NULL"); ++ return -ENOMEM; ++ } + +- y_fb_dma = fb ? (u64)fb->base_y.dma_addr : 0; ++ dst_buf_info = container_of(fb, struct mtk_video_dec_buf, frame_buffer); ++ y_fb_dma = fb->base_y.dma_addr; + if (inst->ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 1) + c_fb_dma = y_fb_dma + + inst->ctx->picinfo.buf_w * inst->ctx->picinfo.buf_h; + else +- c_fb_dma = fb ? (u64)fb->base_c.dma_addr : 0; ++ c_fb_dma = fb->base_c.dma_addr; + + inst->vsi->dec.bs_dma = (u64)bs->dma_addr; + inst->vsi->dec.bs_sz = bs->size; +diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c +index e68fcdaea207aa..c7fdee347ac8ae 100644 +--- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c ++++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c +@@ -865,6 +865,7 @@ static const struct of_device_id rzg2l_csi2_of_table[] = { + { .compatible = "renesas,rzg2l-csi2", }, + { /* sentinel */ } + }; ++MODULE_DEVICE_TABLE(of, rzg2l_csi2_of_table); + + static struct platform_driver rzg2l_csi2_pdrv = { + .remove_new = rzg2l_csi2_remove, +diff --git a/drivers/media/tuners/tuner-i2c.h b/drivers/media/tuners/tuner-i2c.h +index 07aeead0644a31..724952e001cd13 100644 +--- a/drivers/media/tuners/tuner-i2c.h ++++ b/drivers/media/tuners/tuner-i2c.h +@@ -133,10 +133,8 @@ static inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props, + } \ + if (0 == __ret) { \ + state = kzalloc(sizeof(type), GFP_KERNEL); \ +- if (!state) { \ +- __ret = -ENOMEM; \ ++ if (NULL == state) \ + goto __fail; \ +- } \ + state->i2c_props.addr = i2caddr; \ + state->i2c_props.adap = i2cadap; \ + state->i2c_props.name = devname; \ +diff --git a/drivers/mtd/devices/powernv_flash.c b/drivers/mtd/devices/powernv_flash.c +index 66044f4f5bade8..10cd1d9b48859d 100644 +--- a/drivers/mtd/devices/powernv_flash.c ++++ b/drivers/mtd/devices/powernv_flash.c +@@ -207,6 +207,9 @@ static int powernv_flash_set_driver_info(struct device *dev, + * get them + */ + mtd->name = devm_kasprintf(dev, GFP_KERNEL, "%pOFP", dev->of_node); ++ if (!mtd->name) ++ return -ENOMEM; ++ + mtd->type = MTD_NORFLASH; + mtd->flags = MTD_WRITEABLE; + mtd->size = size; +diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c +index 28131a127d065e..8297b366a06699 100644 +--- a/drivers/mtd/devices/slram.c ++++ b/drivers/mtd/devices/slram.c +@@ -296,10 +296,12 @@ static int __init init_slram(void) + T("slram: devname = %s\n", devname); + if ((!map) || (!(devstart = strsep(&map, ",")))) { + E("slram: No devicestart specified.\n"); ++ break; + } + T("slram: devstart = %s\n", devstart); + if ((!map) || (!(devlength = strsep(&map, ",")))) { + E("slram: No devicelength / -end specified.\n"); ++ break; + } + T("slram: devlength = %s\n", devlength); + if (parse_cmdline(devname, devstart, devlength) != 0) { +diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c +index 17477bb2d48ff0..586868b4139f51 100644 +--- a/drivers/mtd/nand/raw/mtk_nand.c ++++ b/drivers/mtd/nand/raw/mtk_nand.c +@@ -1429,16 +1429,32 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc, + return 0; + } + ++static void mtk_nfc_nand_chips_cleanup(struct mtk_nfc *nfc) ++{ ++ struct mtk_nfc_nand_chip *mtk_chip; ++ struct nand_chip *chip; ++ int ret; ++ ++ while (!list_empty(&nfc->chips)) { ++ mtk_chip = list_first_entry(&nfc->chips, ++ struct mtk_nfc_nand_chip, node); ++ chip = &mtk_chip->nand; ++ ret = mtd_device_unregister(nand_to_mtd(chip)); ++ WARN_ON(ret); ++ nand_cleanup(chip); ++ list_del(&mtk_chip->node); ++ } ++} ++ + static int mtk_nfc_nand_chips_init(struct device *dev, struct mtk_nfc *nfc) + { + struct device_node *np = dev->of_node; +- struct device_node *nand_np; + int ret; + +- for_each_child_of_node(np, nand_np) { ++ for_each_child_of_node_scoped(np, nand_np) { + ret = mtk_nfc_nand_chip_init(dev, nfc, nand_np); + if (ret) { +- of_node_put(nand_np); ++ mtk_nfc_nand_chips_cleanup(nfc); + return ret; + } + } +@@ -1570,20 +1586,8 @@ static int mtk_nfc_probe(struct platform_device *pdev) + static void mtk_nfc_remove(struct platform_device *pdev) + { + struct mtk_nfc *nfc = platform_get_drvdata(pdev); +- struct mtk_nfc_nand_chip *mtk_chip; +- struct nand_chip *chip; +- int ret; +- +- while (!list_empty(&nfc->chips)) { +- mtk_chip = list_first_entry(&nfc->chips, +- struct mtk_nfc_nand_chip, node); +- chip = &mtk_chip->nand; +- ret = mtd_device_unregister(nand_to_mtd(chip)); +- WARN_ON(ret); +- nand_cleanup(chip); +- list_del(&mtk_chip->node); +- } + ++ mtk_nfc_nand_chips_cleanup(nfc); + mtk_ecc_release(nfc->ecc); + } + +diff --git a/drivers/net/bareudp.c b/drivers/net/bareudp.c +index 7aca0544fb29c9..e80992b4f9de9a 100644 +--- a/drivers/net/bareudp.c ++++ b/drivers/net/bareudp.c +@@ -68,6 +68,7 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb) + __be16 proto; + void *oiph; + int err; ++ int nh; + + bareudp = rcu_dereference_sk_user_data(sk); + if (!bareudp) +@@ -148,10 +149,25 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb) + } + skb_dst_set(skb, &tun_dst->dst); + skb->dev = bareudp->dev; +- oiph = skb_network_header(skb); +- skb_reset_network_header(skb); + skb_reset_mac_header(skb); + ++ /* Save offset of outer header relative to skb->head, ++ * because we are going to reset the network header to the inner header ++ * and might change skb->head. ++ */ ++ nh = skb_network_header(skb) - skb->head; ++ ++ skb_reset_network_header(skb); ++ ++ if (!pskb_inet_may_pull(skb)) { ++ DEV_STATS_INC(bareudp->dev, rx_length_errors); ++ DEV_STATS_INC(bareudp->dev, rx_errors); ++ goto drop; ++ } ++ ++ /* Get the outer header. */ ++ oiph = skb->head + nh; ++ + if (!ipv6_mod_enabled() || family == AF_INET) + err = IP_ECN_decapsulate(oiph, skb); + else +@@ -301,6 +317,9 @@ static int bareudp_xmit_skb(struct sk_buff *skb, struct net_device *dev, + __be32 saddr; + int err; + ++ if (!skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB))) ++ return -EINVAL; ++ + if (!sock) + return -ESHUTDOWN; + +@@ -368,6 +387,9 @@ static int bareudp6_xmit_skb(struct sk_buff *skb, struct net_device *dev, + __be16 sport; + int err; + ++ if (!skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB))) ++ return -EINVAL; ++ + if (!sock) + return -ESHUTDOWN; + +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 60db34095a2557..3c61f5fbe6b7fe 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -5536,9 +5536,9 @@ bond_xdp_get_xmit_slave(struct net_device *bond_dev, struct xdp_buff *xdp) + break; + + default: +- /* Should never happen. Mode guarded by bond_xdp_check() */ +- netdev_err(bond_dev, "Unknown bonding mode %d for xdp xmit\n", BOND_MODE(bond)); +- WARN_ON_ONCE(1); ++ if (net_ratelimit()) ++ netdev_err(bond_dev, "Unknown bonding mode %d for xdp xmit\n", ++ BOND_MODE(bond)); + return NULL; + } + +diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c +index ddde067f593fcf..0f9f17fdb3bb89 100644 +--- a/drivers/net/can/m_can/m_can.c ++++ b/drivers/net/can/m_can/m_can.c +@@ -1720,11 +1720,7 @@ static int m_can_close(struct net_device *dev) + + netif_stop_queue(dev); + +- if (!cdev->is_peripheral) +- napi_disable(&cdev->napi); +- + m_can_stop(dev); +- m_can_clk_stop(cdev); + free_irq(dev->irq, dev); + + m_can_clean(dev); +@@ -1733,10 +1729,13 @@ static int m_can_close(struct net_device *dev) + destroy_workqueue(cdev->tx_wq); + cdev->tx_wq = NULL; + can_rx_offload_disable(&cdev->offload); ++ } else { ++ napi_disable(&cdev->napi); + } + + close_candev(dev); + ++ m_can_clk_stop(cdev); + phy_power_off(cdev->transceiver); + + return 0; +@@ -1987,6 +1986,8 @@ static int m_can_open(struct net_device *dev) + + if (cdev->is_peripheral) + can_rx_offload_enable(&cdev->offload); ++ else ++ napi_enable(&cdev->napi); + + /* register interrupt handler */ + if (cdev->is_peripheral) { +@@ -2020,9 +2021,6 @@ static int m_can_open(struct net_device *dev) + if (err) + goto exit_start_fail; + +- if (!cdev->is_peripheral) +- napi_enable(&cdev->napi); +- + netif_start_queue(dev); + + return 0; +@@ -2036,6 +2034,8 @@ static int m_can_open(struct net_device *dev) + out_wq_fail: + if (cdev->is_peripheral) + can_rx_offload_disable(&cdev->offload); ++ else ++ napi_disable(&cdev->napi); + close_candev(dev); + exit_disable_clks: + m_can_clk_stop(cdev); +diff --git a/drivers/net/can/usb/esd_usb.c b/drivers/net/can/usb/esd_usb.c +index 41a0e4261d15e9..03ad10b01867d8 100644 +--- a/drivers/net/can/usb/esd_usb.c ++++ b/drivers/net/can/usb/esd_usb.c +@@ -3,7 +3,7 @@ + * CAN driver for esd electronics gmbh CAN-USB/2, CAN-USB/3 and CAN-USB/Micro + * + * Copyright (C) 2010-2012 esd electronic system design gmbh, Matthias Fuchs <socketcan@esd.eu> +- * Copyright (C) 2022-2023 esd electronics gmbh, Frank Jungclaus <frank.jungclaus@esd.eu> ++ * Copyright (C) 2022-2024 esd electronics gmbh, Frank Jungclaus <frank.jungclaus@esd.eu> + */ + + #include <linux/can.h> +@@ -1116,9 +1116,6 @@ static int esd_usb_3_set_bittiming(struct net_device *netdev) + if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) + flags |= ESD_USB_3_BAUDRATE_FLAG_LOM; + +- if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) +- flags |= ESD_USB_3_BAUDRATE_FLAG_TRS; +- + baud_x->nom.brp = cpu_to_le16(nom_bt->brp & (nom_btc->brp_max - 1)); + baud_x->nom.sjw = cpu_to_le16(nom_bt->sjw & (nom_btc->sjw_max - 1)); + baud_x->nom.tseg1 = cpu_to_le16((nom_bt->prop_seg + nom_bt->phase_seg1) +@@ -1219,7 +1216,6 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index) + switch (le16_to_cpu(dev->udev->descriptor.idProduct)) { + case ESD_USB_CANUSB3_PRODUCT_ID: + priv->can.clock.freq = ESD_USB_3_CAN_CLOCK; +- priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; + priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD; + priv->can.bittiming_const = &esd_usb_3_nom_bittiming_const; + priv->can.data_bittiming_const = &esd_usb_3_data_bittiming_const; +diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c +index 5c45f42232d326..f04f42ea60c0f7 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc.c +@@ -2305,12 +2305,11 @@ static int enetc_setup_irqs(struct enetc_ndev_priv *priv) + + snprintf(v->name, sizeof(v->name), "%s-rxtx%d", + priv->ndev->name, i); +- err = request_irq(irq, enetc_msix, 0, v->name, v); ++ err = request_irq(irq, enetc_msix, IRQF_NO_AUTOEN, v->name, v); + if (err) { + dev_err(priv->dev, "request_irq() failed!\n"); + goto irq_err; + } +- disable_irq(irq); + + v->tbier_base = hw->reg + ENETC_BDR(TX, 0, ENETC_TBIER); + v->rbier = hw->reg + ENETC_BDR(RX, i, ENETC_RBIER); +diff --git a/drivers/net/ethernet/intel/idpf/idpf.h b/drivers/net/ethernet/intel/idpf/idpf.h +index e7a03653824659..f9e43d171f1712 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf.h ++++ b/drivers/net/ethernet/intel/idpf/idpf.h +@@ -17,10 +17,8 @@ struct idpf_vport_max_q; + #include <linux/sctp.h> + #include <linux/ethtool_netlink.h> + #include <net/gro.h> +-#include <linux/dim.h> + + #include "virtchnl2.h" +-#include "idpf_lan_txrx.h" + #include "idpf_txrx.h" + #include "idpf_controlq.h" + +@@ -302,7 +300,7 @@ struct idpf_vport { + u16 num_txq_grp; + struct idpf_txq_group *txq_grps; + u32 txq_model; +- struct idpf_queue **txqs; ++ struct idpf_tx_queue **txqs; + bool crc_enable; + + u16 num_rxq; +diff --git a/drivers/net/ethernet/intel/idpf/idpf_ethtool.c b/drivers/net/ethernet/intel/idpf/idpf_ethtool.c +index 1885ba618981df..e933fed16c7ea5 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_ethtool.c ++++ b/drivers/net/ethernet/intel/idpf/idpf_ethtool.c +@@ -437,22 +437,24 @@ struct idpf_stats { + .stat_offset = offsetof(_type, _stat) \ + } + +-/* Helper macro for defining some statistics related to queues */ +-#define IDPF_QUEUE_STAT(_name, _stat) \ +- IDPF_STAT(struct idpf_queue, _name, _stat) ++/* Helper macros for defining some statistics related to queues */ ++#define IDPF_RX_QUEUE_STAT(_name, _stat) \ ++ IDPF_STAT(struct idpf_rx_queue, _name, _stat) ++#define IDPF_TX_QUEUE_STAT(_name, _stat) \ ++ IDPF_STAT(struct idpf_tx_queue, _name, _stat) + + /* Stats associated with a Tx queue */ + static const struct idpf_stats idpf_gstrings_tx_queue_stats[] = { +- IDPF_QUEUE_STAT("pkts", q_stats.tx.packets), +- IDPF_QUEUE_STAT("bytes", q_stats.tx.bytes), +- IDPF_QUEUE_STAT("lso_pkts", q_stats.tx.lso_pkts), ++ IDPF_TX_QUEUE_STAT("pkts", q_stats.packets), ++ IDPF_TX_QUEUE_STAT("bytes", q_stats.bytes), ++ IDPF_TX_QUEUE_STAT("lso_pkts", q_stats.lso_pkts), + }; + + /* Stats associated with an Rx queue */ + static const struct idpf_stats idpf_gstrings_rx_queue_stats[] = { +- IDPF_QUEUE_STAT("pkts", q_stats.rx.packets), +- IDPF_QUEUE_STAT("bytes", q_stats.rx.bytes), +- IDPF_QUEUE_STAT("rx_gro_hw_pkts", q_stats.rx.rsc_pkts), ++ IDPF_RX_QUEUE_STAT("pkts", q_stats.packets), ++ IDPF_RX_QUEUE_STAT("bytes", q_stats.bytes), ++ IDPF_RX_QUEUE_STAT("rx_gro_hw_pkts", q_stats.rsc_pkts), + }; + + #define IDPF_TX_QUEUE_STATS_LEN ARRAY_SIZE(idpf_gstrings_tx_queue_stats) +@@ -633,7 +635,7 @@ static int idpf_get_sset_count(struct net_device *netdev, int sset) + * Copies the stat data defined by the pointer and stat structure pair into + * the memory supplied as data. If the pointer is null, data will be zero'd. + */ +-static void idpf_add_one_ethtool_stat(u64 *data, void *pstat, ++static void idpf_add_one_ethtool_stat(u64 *data, const void *pstat, + const struct idpf_stats *stat) + { + char *p; +@@ -671,6 +673,7 @@ static void idpf_add_one_ethtool_stat(u64 *data, void *pstat, + * idpf_add_queue_stats - copy queue statistics into supplied buffer + * @data: ethtool stats buffer + * @q: the queue to copy ++ * @type: type of the queue + * + * Queue statistics must be copied while protected by u64_stats_fetch_begin, + * so we can't directly use idpf_add_ethtool_stats. Assumes that queue stats +@@ -681,19 +684,23 @@ static void idpf_add_one_ethtool_stat(u64 *data, void *pstat, + * + * This function expects to be called while under rcu_read_lock(). + */ +-static void idpf_add_queue_stats(u64 **data, struct idpf_queue *q) ++static void idpf_add_queue_stats(u64 **data, const void *q, ++ enum virtchnl2_queue_type type) + { ++ const struct u64_stats_sync *stats_sync; + const struct idpf_stats *stats; + unsigned int start; + unsigned int size; + unsigned int i; + +- if (q->q_type == VIRTCHNL2_QUEUE_TYPE_RX) { ++ if (type == VIRTCHNL2_QUEUE_TYPE_RX) { + size = IDPF_RX_QUEUE_STATS_LEN; + stats = idpf_gstrings_rx_queue_stats; ++ stats_sync = &((const struct idpf_rx_queue *)q)->stats_sync; + } else { + size = IDPF_TX_QUEUE_STATS_LEN; + stats = idpf_gstrings_tx_queue_stats; ++ stats_sync = &((const struct idpf_tx_queue *)q)->stats_sync; + } + + /* To avoid invalid statistics values, ensure that we keep retrying +@@ -701,10 +708,10 @@ static void idpf_add_queue_stats(u64 **data, struct idpf_queue *q) + * u64_stats_fetch_retry. + */ + do { +- start = u64_stats_fetch_begin(&q->stats_sync); ++ start = u64_stats_fetch_begin(stats_sync); + for (i = 0; i < size; i++) + idpf_add_one_ethtool_stat(&(*data)[i], q, &stats[i]); +- } while (u64_stats_fetch_retry(&q->stats_sync, start)); ++ } while (u64_stats_fetch_retry(stats_sync, start)); + + /* Once we successfully copy the stats in, update the data pointer */ + *data += size; +@@ -793,7 +800,7 @@ static void idpf_collect_queue_stats(struct idpf_vport *vport) + for (j = 0; j < num_rxq; j++) { + u64 hw_csum_err, hsplit, hsplit_hbo, bad_descs; + struct idpf_rx_queue_stats *stats; +- struct idpf_queue *rxq; ++ struct idpf_rx_queue *rxq; + unsigned int start; + + if (idpf_is_queue_model_split(vport->rxq_model)) +@@ -807,7 +814,7 @@ static void idpf_collect_queue_stats(struct idpf_vport *vport) + do { + start = u64_stats_fetch_begin(&rxq->stats_sync); + +- stats = &rxq->q_stats.rx; ++ stats = &rxq->q_stats; + hw_csum_err = u64_stats_read(&stats->hw_csum_err); + hsplit = u64_stats_read(&stats->hsplit_pkts); + hsplit_hbo = u64_stats_read(&stats->hsplit_buf_ovf); +@@ -828,7 +835,7 @@ static void idpf_collect_queue_stats(struct idpf_vport *vport) + + for (j = 0; j < txq_grp->num_txq; j++) { + u64 linearize, qbusy, skb_drops, dma_map_errs; +- struct idpf_queue *txq = txq_grp->txqs[j]; ++ struct idpf_tx_queue *txq = txq_grp->txqs[j]; + struct idpf_tx_queue_stats *stats; + unsigned int start; + +@@ -838,7 +845,7 @@ static void idpf_collect_queue_stats(struct idpf_vport *vport) + do { + start = u64_stats_fetch_begin(&txq->stats_sync); + +- stats = &txq->q_stats.tx; ++ stats = &txq->q_stats; + linearize = u64_stats_read(&stats->linearize); + qbusy = u64_stats_read(&stats->q_busy); + skb_drops = u64_stats_read(&stats->skb_drops); +@@ -896,12 +903,12 @@ static void idpf_get_ethtool_stats(struct net_device *netdev, + qtype = VIRTCHNL2_QUEUE_TYPE_TX; + + for (j = 0; j < txq_grp->num_txq; j++, total++) { +- struct idpf_queue *txq = txq_grp->txqs[j]; ++ struct idpf_tx_queue *txq = txq_grp->txqs[j]; + + if (!txq) + idpf_add_empty_queue_stats(&data, qtype); + else +- idpf_add_queue_stats(&data, txq); ++ idpf_add_queue_stats(&data, txq, qtype); + } + } + +@@ -929,7 +936,7 @@ static void idpf_get_ethtool_stats(struct net_device *netdev, + num_rxq = rxq_grp->singleq.num_rxq; + + for (j = 0; j < num_rxq; j++, total++) { +- struct idpf_queue *rxq; ++ struct idpf_rx_queue *rxq; + + if (is_splitq) + rxq = &rxq_grp->splitq.rxq_sets[j]->rxq; +@@ -938,7 +945,7 @@ static void idpf_get_ethtool_stats(struct net_device *netdev, + if (!rxq) + idpf_add_empty_queue_stats(&data, qtype); + else +- idpf_add_queue_stats(&data, rxq); ++ idpf_add_queue_stats(&data, rxq, qtype); + + /* In splitq mode, don't get page pool stats here since + * the pools are attached to the buffer queues +@@ -953,7 +960,7 @@ static void idpf_get_ethtool_stats(struct net_device *netdev, + + for (i = 0; i < vport->num_rxq_grp; i++) { + for (j = 0; j < vport->num_bufqs_per_qgrp; j++) { +- struct idpf_queue *rxbufq = ++ struct idpf_buf_queue *rxbufq = + &vport->rxq_grps[i].splitq.bufq_sets[j].bufq; + + page_pool_get_stats(rxbufq->pp, &pp_stats); +@@ -971,60 +978,64 @@ static void idpf_get_ethtool_stats(struct net_device *netdev, + } + + /** +- * idpf_find_rxq - find rxq from q index ++ * idpf_find_rxq_vec - find rxq vector from q index + * @vport: virtual port associated to queue + * @q_num: q index used to find queue + * +- * returns pointer to rx queue ++ * returns pointer to rx vector + */ +-static struct idpf_queue *idpf_find_rxq(struct idpf_vport *vport, int q_num) ++static struct idpf_q_vector *idpf_find_rxq_vec(const struct idpf_vport *vport, ++ int q_num) + { + int q_grp, q_idx; + + if (!idpf_is_queue_model_split(vport->rxq_model)) +- return vport->rxq_grps->singleq.rxqs[q_num]; ++ return vport->rxq_grps->singleq.rxqs[q_num]->q_vector; + + q_grp = q_num / IDPF_DFLT_SPLITQ_RXQ_PER_GROUP; + q_idx = q_num % IDPF_DFLT_SPLITQ_RXQ_PER_GROUP; + +- return &vport->rxq_grps[q_grp].splitq.rxq_sets[q_idx]->rxq; ++ return vport->rxq_grps[q_grp].splitq.rxq_sets[q_idx]->rxq.q_vector; + } + + /** +- * idpf_find_txq - find txq from q index ++ * idpf_find_txq_vec - find txq vector from q index + * @vport: virtual port associated to queue + * @q_num: q index used to find queue + * +- * returns pointer to tx queue ++ * returns pointer to tx vector + */ +-static struct idpf_queue *idpf_find_txq(struct idpf_vport *vport, int q_num) ++static struct idpf_q_vector *idpf_find_txq_vec(const struct idpf_vport *vport, ++ int q_num) + { + int q_grp; + + if (!idpf_is_queue_model_split(vport->txq_model)) +- return vport->txqs[q_num]; ++ return vport->txqs[q_num]->q_vector; + + q_grp = q_num / IDPF_DFLT_SPLITQ_TXQ_PER_GROUP; + +- return vport->txq_grps[q_grp].complq; ++ return vport->txq_grps[q_grp].complq->q_vector; + } + + /** + * __idpf_get_q_coalesce - get ITR values for specific queue + * @ec: ethtool structure to fill with driver's coalesce settings +- * @q: quuee of Rx or Tx ++ * @q_vector: queue vector corresponding to this queue ++ * @type: queue type + */ + static void __idpf_get_q_coalesce(struct ethtool_coalesce *ec, +- struct idpf_queue *q) ++ const struct idpf_q_vector *q_vector, ++ enum virtchnl2_queue_type type) + { +- if (q->q_type == VIRTCHNL2_QUEUE_TYPE_RX) { ++ if (type == VIRTCHNL2_QUEUE_TYPE_RX) { + ec->use_adaptive_rx_coalesce = +- IDPF_ITR_IS_DYNAMIC(q->q_vector->rx_intr_mode); +- ec->rx_coalesce_usecs = q->q_vector->rx_itr_value; ++ IDPF_ITR_IS_DYNAMIC(q_vector->rx_intr_mode); ++ ec->rx_coalesce_usecs = q_vector->rx_itr_value; + } else { + ec->use_adaptive_tx_coalesce = +- IDPF_ITR_IS_DYNAMIC(q->q_vector->tx_intr_mode); +- ec->tx_coalesce_usecs = q->q_vector->tx_itr_value; ++ IDPF_ITR_IS_DYNAMIC(q_vector->tx_intr_mode); ++ ec->tx_coalesce_usecs = q_vector->tx_itr_value; + } + } + +@@ -1040,8 +1051,8 @@ static int idpf_get_q_coalesce(struct net_device *netdev, + struct ethtool_coalesce *ec, + u32 q_num) + { +- struct idpf_netdev_priv *np = netdev_priv(netdev); +- struct idpf_vport *vport; ++ const struct idpf_netdev_priv *np = netdev_priv(netdev); ++ const struct idpf_vport *vport; + int err = 0; + + idpf_vport_ctrl_lock(netdev); +@@ -1056,10 +1067,12 @@ static int idpf_get_q_coalesce(struct net_device *netdev, + } + + if (q_num < vport->num_rxq) +- __idpf_get_q_coalesce(ec, idpf_find_rxq(vport, q_num)); ++ __idpf_get_q_coalesce(ec, idpf_find_rxq_vec(vport, q_num), ++ VIRTCHNL2_QUEUE_TYPE_RX); + + if (q_num < vport->num_txq) +- __idpf_get_q_coalesce(ec, idpf_find_txq(vport, q_num)); ++ __idpf_get_q_coalesce(ec, idpf_find_txq_vec(vport, q_num), ++ VIRTCHNL2_QUEUE_TYPE_TX); + + unlock_mutex: + idpf_vport_ctrl_unlock(netdev); +@@ -1103,16 +1116,15 @@ static int idpf_get_per_q_coalesce(struct net_device *netdev, u32 q_num, + /** + * __idpf_set_q_coalesce - set ITR values for specific queue + * @ec: ethtool structure from user to update ITR settings +- * @q: queue for which itr values has to be set ++ * @qv: queue vector for which itr values has to be set + * @is_rxq: is queue type rx + * + * Returns 0 on success, negative otherwise. + */ +-static int __idpf_set_q_coalesce(struct ethtool_coalesce *ec, +- struct idpf_queue *q, bool is_rxq) ++static int __idpf_set_q_coalesce(const struct ethtool_coalesce *ec, ++ struct idpf_q_vector *qv, bool is_rxq) + { + u32 use_adaptive_coalesce, coalesce_usecs; +- struct idpf_q_vector *qv = q->q_vector; + bool is_dim_ena = false; + u16 itr_val; + +@@ -1128,7 +1140,7 @@ static int __idpf_set_q_coalesce(struct ethtool_coalesce *ec, + itr_val = qv->tx_itr_value; + } + if (coalesce_usecs != itr_val && use_adaptive_coalesce) { +- netdev_err(q->vport->netdev, "Cannot set coalesce usecs if adaptive enabled\n"); ++ netdev_err(qv->vport->netdev, "Cannot set coalesce usecs if adaptive enabled\n"); + + return -EINVAL; + } +@@ -1137,7 +1149,7 @@ static int __idpf_set_q_coalesce(struct ethtool_coalesce *ec, + return 0; + + if (coalesce_usecs > IDPF_ITR_MAX) { +- netdev_err(q->vport->netdev, ++ netdev_err(qv->vport->netdev, + "Invalid value, %d-usecs range is 0-%d\n", + coalesce_usecs, IDPF_ITR_MAX); + +@@ -1146,7 +1158,7 @@ static int __idpf_set_q_coalesce(struct ethtool_coalesce *ec, + + if (coalesce_usecs % 2) { + coalesce_usecs--; +- netdev_info(q->vport->netdev, ++ netdev_info(qv->vport->netdev, + "HW only supports even ITR values, ITR rounded to %d\n", + coalesce_usecs); + } +@@ -1185,15 +1197,16 @@ static int __idpf_set_q_coalesce(struct ethtool_coalesce *ec, + * + * Return 0 on success, and negative on failure + */ +-static int idpf_set_q_coalesce(struct idpf_vport *vport, +- struct ethtool_coalesce *ec, ++static int idpf_set_q_coalesce(const struct idpf_vport *vport, ++ const struct ethtool_coalesce *ec, + int q_num, bool is_rxq) + { +- struct idpf_queue *q; ++ struct idpf_q_vector *qv; + +- q = is_rxq ? idpf_find_rxq(vport, q_num) : idpf_find_txq(vport, q_num); ++ qv = is_rxq ? idpf_find_rxq_vec(vport, q_num) : ++ idpf_find_txq_vec(vport, q_num); + +- if (q && __idpf_set_q_coalesce(ec, q, is_rxq)) ++ if (qv && __idpf_set_q_coalesce(ec, qv, is_rxq)) + return -EINVAL; + + return 0; +diff --git a/drivers/net/ethernet/intel/idpf/idpf_lan_txrx.h b/drivers/net/ethernet/intel/idpf/idpf_lan_txrx.h +index a5752dcab8887c..8c7f8ef8f1a153 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_lan_txrx.h ++++ b/drivers/net/ethernet/intel/idpf/idpf_lan_txrx.h +@@ -4,6 +4,8 @@ + #ifndef _IDPF_LAN_TXRX_H_ + #define _IDPF_LAN_TXRX_H_ + ++#include <linux/bits.h> ++ + enum idpf_rss_hash { + IDPF_HASH_INVALID = 0, + /* Values 1 - 28 are reserved for future use */ +diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c b/drivers/net/ethernet/intel/idpf/idpf_lib.c +index 3ac9d7ab83f20f..5e336f64bc25e3 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c ++++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c +@@ -4,8 +4,7 @@ + #include "idpf.h" + #include "idpf_virtchnl.h" + +-static const struct net_device_ops idpf_netdev_ops_splitq; +-static const struct net_device_ops idpf_netdev_ops_singleq; ++static const struct net_device_ops idpf_netdev_ops; + + /** + * idpf_init_vector_stack - Fill the MSIX vector stack with vector index +@@ -765,10 +764,7 @@ static int idpf_cfg_netdev(struct idpf_vport *vport) + } + + /* assign netdev_ops */ +- if (idpf_is_queue_model_split(vport->txq_model)) +- netdev->netdev_ops = &idpf_netdev_ops_splitq; +- else +- netdev->netdev_ops = &idpf_netdev_ops_singleq; ++ netdev->netdev_ops = &idpf_netdev_ops; + + /* setup watchdog timeout value to be 5 second */ + netdev->watchdog_timeo = 5 * HZ; +@@ -1318,14 +1314,14 @@ static void idpf_rx_init_buf_tail(struct idpf_vport *vport) + + if (idpf_is_queue_model_split(vport->rxq_model)) { + for (j = 0; j < vport->num_bufqs_per_qgrp; j++) { +- struct idpf_queue *q = ++ const struct idpf_buf_queue *q = + &grp->splitq.bufq_sets[j].bufq; + + writel(q->next_to_alloc, q->tail); + } + } else { + for (j = 0; j < grp->singleq.num_rxq; j++) { +- struct idpf_queue *q = ++ const struct idpf_rx_queue *q = + grp->singleq.rxqs[j]; + + writel(q->next_to_alloc, q->tail); +@@ -1852,7 +1848,7 @@ int idpf_initiate_soft_reset(struct idpf_vport *vport, + enum idpf_vport_state current_state = np->state; + struct idpf_adapter *adapter = vport->adapter; + struct idpf_vport *new_vport; +- int err, i; ++ int err; + + /* If the system is low on memory, we can end up in bad state if we + * free all the memory for queue resources and try to allocate them +@@ -1923,46 +1919,6 @@ int idpf_initiate_soft_reset(struct idpf_vport *vport, + */ + memcpy(vport, new_vport, offsetof(struct idpf_vport, link_speed_mbps)); + +- /* Since idpf_vport_queues_alloc was called with new_port, the queue +- * back pointers are currently pointing to the local new_vport. Reset +- * the backpointers to the original vport here +- */ +- for (i = 0; i < vport->num_txq_grp; i++) { +- struct idpf_txq_group *tx_qgrp = &vport->txq_grps[i]; +- int j; +- +- tx_qgrp->vport = vport; +- for (j = 0; j < tx_qgrp->num_txq; j++) +- tx_qgrp->txqs[j]->vport = vport; +- +- if (idpf_is_queue_model_split(vport->txq_model)) +- tx_qgrp->complq->vport = vport; +- } +- +- for (i = 0; i < vport->num_rxq_grp; i++) { +- struct idpf_rxq_group *rx_qgrp = &vport->rxq_grps[i]; +- struct idpf_queue *q; +- u16 num_rxq; +- int j; +- +- rx_qgrp->vport = vport; +- for (j = 0; j < vport->num_bufqs_per_qgrp; j++) +- rx_qgrp->splitq.bufq_sets[j].bufq.vport = vport; +- +- if (idpf_is_queue_model_split(vport->rxq_model)) +- num_rxq = rx_qgrp->splitq.num_rxq_sets; +- else +- num_rxq = rx_qgrp->singleq.num_rxq; +- +- for (j = 0; j < num_rxq; j++) { +- if (idpf_is_queue_model_split(vport->rxq_model)) +- q = &rx_qgrp->splitq.rxq_sets[j]->rxq; +- else +- q = rx_qgrp->singleq.rxqs[j]; +- q->vport = vport; +- } +- } +- + if (reset_cause == IDPF_SR_Q_CHANGE) + idpf_vport_alloc_vec_indexes(vport); + +@@ -2393,24 +2349,10 @@ void idpf_free_dma_mem(struct idpf_hw *hw, struct idpf_dma_mem *mem) + mem->pa = 0; + } + +-static const struct net_device_ops idpf_netdev_ops_splitq = { +- .ndo_open = idpf_open, +- .ndo_stop = idpf_stop, +- .ndo_start_xmit = idpf_tx_splitq_start, +- .ndo_features_check = idpf_features_check, +- .ndo_set_rx_mode = idpf_set_rx_mode, +- .ndo_validate_addr = eth_validate_addr, +- .ndo_set_mac_address = idpf_set_mac, +- .ndo_change_mtu = idpf_change_mtu, +- .ndo_get_stats64 = idpf_get_stats64, +- .ndo_set_features = idpf_set_features, +- .ndo_tx_timeout = idpf_tx_timeout, +-}; +- +-static const struct net_device_ops idpf_netdev_ops_singleq = { ++static const struct net_device_ops idpf_netdev_ops = { + .ndo_open = idpf_open, + .ndo_stop = idpf_stop, +- .ndo_start_xmit = idpf_tx_singleq_start, ++ .ndo_start_xmit = idpf_tx_start, + .ndo_features_check = idpf_features_check, + .ndo_set_rx_mode = idpf_set_rx_mode, + .ndo_validate_addr = eth_validate_addr, +diff --git a/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c b/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c +index 27b93592c4babb..5e5fa2d0aa4d18 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c ++++ b/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c +@@ -186,7 +186,7 @@ static int idpf_tx_singleq_csum(struct sk_buff *skb, + * and gets a physical address for each memory location and programs + * it and the length into the transmit base mode descriptor. + */ +-static void idpf_tx_singleq_map(struct idpf_queue *tx_q, ++static void idpf_tx_singleq_map(struct idpf_tx_queue *tx_q, + struct idpf_tx_buf *first, + struct idpf_tx_offload_params *offloads) + { +@@ -205,12 +205,12 @@ static void idpf_tx_singleq_map(struct idpf_queue *tx_q, + data_len = skb->data_len; + size = skb_headlen(skb); + +- tx_desc = IDPF_BASE_TX_DESC(tx_q, i); ++ tx_desc = &tx_q->base_tx[i]; + + dma = dma_map_single(tx_q->dev, skb->data, size, DMA_TO_DEVICE); + + /* write each descriptor with CRC bit */ +- if (tx_q->vport->crc_enable) ++ if (idpf_queue_has(CRC_EN, tx_q)) + td_cmd |= IDPF_TX_DESC_CMD_ICRC; + + for (frag = &skb_shinfo(skb)->frags[0];; frag++) { +@@ -239,7 +239,7 @@ static void idpf_tx_singleq_map(struct idpf_queue *tx_q, + i++; + + if (i == tx_q->desc_count) { +- tx_desc = IDPF_BASE_TX_DESC(tx_q, 0); ++ tx_desc = &tx_q->base_tx[0]; + i = 0; + } + +@@ -259,7 +259,7 @@ static void idpf_tx_singleq_map(struct idpf_queue *tx_q, + i++; + + if (i == tx_q->desc_count) { +- tx_desc = IDPF_BASE_TX_DESC(tx_q, 0); ++ tx_desc = &tx_q->base_tx[0]; + i = 0; + } + +@@ -285,7 +285,7 @@ static void idpf_tx_singleq_map(struct idpf_queue *tx_q, + /* set next_to_watch value indicating a packet is present */ + first->next_to_watch = tx_desc; + +- nq = netdev_get_tx_queue(tx_q->vport->netdev, tx_q->idx); ++ nq = netdev_get_tx_queue(tx_q->netdev, tx_q->idx); + netdev_tx_sent_queue(nq, first->bytecount); + + idpf_tx_buf_hw_update(tx_q, i, netdev_xmit_more()); +@@ -299,7 +299,7 @@ static void idpf_tx_singleq_map(struct idpf_queue *tx_q, + * ring entry to reflect that this index is a context descriptor + */ + static struct idpf_base_tx_ctx_desc * +-idpf_tx_singleq_get_ctx_desc(struct idpf_queue *txq) ++idpf_tx_singleq_get_ctx_desc(struct idpf_tx_queue *txq) + { + struct idpf_base_tx_ctx_desc *ctx_desc; + int ntu = txq->next_to_use; +@@ -307,7 +307,7 @@ idpf_tx_singleq_get_ctx_desc(struct idpf_queue *txq) + memset(&txq->tx_buf[ntu], 0, sizeof(struct idpf_tx_buf)); + txq->tx_buf[ntu].ctx_entry = true; + +- ctx_desc = IDPF_BASE_TX_CTX_DESC(txq, ntu); ++ ctx_desc = &txq->base_ctx[ntu]; + + IDPF_SINGLEQ_BUMP_RING_IDX(txq, ntu); + txq->next_to_use = ntu; +@@ -320,7 +320,7 @@ idpf_tx_singleq_get_ctx_desc(struct idpf_queue *txq) + * @txq: queue to send buffer on + * @offload: offload parameter structure + **/ +-static void idpf_tx_singleq_build_ctx_desc(struct idpf_queue *txq, ++static void idpf_tx_singleq_build_ctx_desc(struct idpf_tx_queue *txq, + struct idpf_tx_offload_params *offload) + { + struct idpf_base_tx_ctx_desc *desc = idpf_tx_singleq_get_ctx_desc(txq); +@@ -333,7 +333,7 @@ static void idpf_tx_singleq_build_ctx_desc(struct idpf_queue *txq, + qw1 |= FIELD_PREP(IDPF_TXD_CTX_QW1_MSS_M, offload->mss); + + u64_stats_update_begin(&txq->stats_sync); +- u64_stats_inc(&txq->q_stats.tx.lso_pkts); ++ u64_stats_inc(&txq->q_stats.lso_pkts); + u64_stats_update_end(&txq->stats_sync); + } + +@@ -351,8 +351,8 @@ static void idpf_tx_singleq_build_ctx_desc(struct idpf_queue *txq, + * + * Returns NETDEV_TX_OK if sent, else an error code + */ +-static netdev_tx_t idpf_tx_singleq_frame(struct sk_buff *skb, +- struct idpf_queue *tx_q) ++netdev_tx_t idpf_tx_singleq_frame(struct sk_buff *skb, ++ struct idpf_tx_queue *tx_q) + { + struct idpf_tx_offload_params offload = { }; + struct idpf_tx_buf *first; +@@ -369,6 +369,10 @@ static netdev_tx_t idpf_tx_singleq_frame(struct sk_buff *skb, + IDPF_TX_DESCS_FOR_CTX)) { + idpf_tx_buf_hw_update(tx_q, tx_q->next_to_use, false); + ++ u64_stats_update_begin(&tx_q->stats_sync); ++ u64_stats_inc(&tx_q->q_stats.q_busy); ++ u64_stats_update_end(&tx_q->stats_sync); ++ + return NETDEV_TX_BUSY; + } + +@@ -408,33 +412,6 @@ static netdev_tx_t idpf_tx_singleq_frame(struct sk_buff *skb, + return idpf_tx_drop_skb(tx_q, skb); + } + +-/** +- * idpf_tx_singleq_start - Selects the right Tx queue to send buffer +- * @skb: send buffer +- * @netdev: network interface device structure +- * +- * Returns NETDEV_TX_OK if sent, else an error code +- */ +-netdev_tx_t idpf_tx_singleq_start(struct sk_buff *skb, +- struct net_device *netdev) +-{ +- struct idpf_vport *vport = idpf_netdev_to_vport(netdev); +- struct idpf_queue *tx_q; +- +- tx_q = vport->txqs[skb_get_queue_mapping(skb)]; +- +- /* hardware can't handle really short frames, hardware padding works +- * beyond this point +- */ +- if (skb_put_padto(skb, IDPF_TX_MIN_PKT_LEN)) { +- idpf_tx_buf_hw_update(tx_q, tx_q->next_to_use, false); +- +- return NETDEV_TX_OK; +- } +- +- return idpf_tx_singleq_frame(skb, tx_q); +-} +- + /** + * idpf_tx_singleq_clean - Reclaim resources from queue + * @tx_q: Tx queue to clean +@@ -442,20 +419,19 @@ netdev_tx_t idpf_tx_singleq_start(struct sk_buff *skb, + * @cleaned: returns number of packets cleaned + * + */ +-static bool idpf_tx_singleq_clean(struct idpf_queue *tx_q, int napi_budget, ++static bool idpf_tx_singleq_clean(struct idpf_tx_queue *tx_q, int napi_budget, + int *cleaned) + { +- unsigned int budget = tx_q->vport->compln_clean_budget; + unsigned int total_bytes = 0, total_pkts = 0; + struct idpf_base_tx_desc *tx_desc; ++ u32 budget = tx_q->clean_budget; + s16 ntc = tx_q->next_to_clean; + struct idpf_netdev_priv *np; + struct idpf_tx_buf *tx_buf; +- struct idpf_vport *vport; + struct netdev_queue *nq; + bool dont_wake; + +- tx_desc = IDPF_BASE_TX_DESC(tx_q, ntc); ++ tx_desc = &tx_q->base_tx[ntc]; + tx_buf = &tx_q->tx_buf[ntc]; + ntc -= tx_q->desc_count; + +@@ -517,7 +493,7 @@ static bool idpf_tx_singleq_clean(struct idpf_queue *tx_q, int napi_budget, + if (unlikely(!ntc)) { + ntc -= tx_q->desc_count; + tx_buf = tx_q->tx_buf; +- tx_desc = IDPF_BASE_TX_DESC(tx_q, 0); ++ tx_desc = &tx_q->base_tx[0]; + } + + /* unmap any remaining paged data */ +@@ -540,7 +516,7 @@ static bool idpf_tx_singleq_clean(struct idpf_queue *tx_q, int napi_budget, + if (unlikely(!ntc)) { + ntc -= tx_q->desc_count; + tx_buf = tx_q->tx_buf; +- tx_desc = IDPF_BASE_TX_DESC(tx_q, 0); ++ tx_desc = &tx_q->base_tx[0]; + } + } while (likely(budget)); + +@@ -550,16 +526,15 @@ static bool idpf_tx_singleq_clean(struct idpf_queue *tx_q, int napi_budget, + *cleaned += total_pkts; + + u64_stats_update_begin(&tx_q->stats_sync); +- u64_stats_add(&tx_q->q_stats.tx.packets, total_pkts); +- u64_stats_add(&tx_q->q_stats.tx.bytes, total_bytes); ++ u64_stats_add(&tx_q->q_stats.packets, total_pkts); ++ u64_stats_add(&tx_q->q_stats.bytes, total_bytes); + u64_stats_update_end(&tx_q->stats_sync); + +- vport = tx_q->vport; +- np = netdev_priv(vport->netdev); +- nq = netdev_get_tx_queue(vport->netdev, tx_q->idx); ++ np = netdev_priv(tx_q->netdev); ++ nq = netdev_get_tx_queue(tx_q->netdev, tx_q->idx); + + dont_wake = np->state != __IDPF_VPORT_UP || +- !netif_carrier_ok(vport->netdev); ++ !netif_carrier_ok(tx_q->netdev); + __netif_txq_completed_wake(nq, total_pkts, total_bytes, + IDPF_DESC_UNUSED(tx_q), IDPF_TX_WAKE_THRESH, + dont_wake); +@@ -584,7 +559,7 @@ static bool idpf_tx_singleq_clean_all(struct idpf_q_vector *q_vec, int budget, + + budget_per_q = num_txq ? max(budget / num_txq, 1) : 0; + for (i = 0; i < num_txq; i++) { +- struct idpf_queue *q; ++ struct idpf_tx_queue *q; + + q = q_vec->tx[i]; + clean_complete &= idpf_tx_singleq_clean(q, budget_per_q, +@@ -614,14 +589,9 @@ static bool idpf_rx_singleq_test_staterr(const union virtchnl2_rx_desc *rx_desc, + + /** + * idpf_rx_singleq_is_non_eop - process handling of non-EOP buffers +- * @rxq: Rx ring being processed + * @rx_desc: Rx descriptor for current buffer +- * @skb: Current socket buffer containing buffer in progress +- * @ntc: next to clean + */ +-static bool idpf_rx_singleq_is_non_eop(struct idpf_queue *rxq, +- union virtchnl2_rx_desc *rx_desc, +- struct sk_buff *skb, u16 ntc) ++static bool idpf_rx_singleq_is_non_eop(const union virtchnl2_rx_desc *rx_desc) + { + /* if we are the last buffer then there is nothing else to do */ + if (likely(idpf_rx_singleq_test_staterr(rx_desc, IDPF_RXD_EOF_SINGLEQ))) +@@ -639,7 +609,7 @@ static bool idpf_rx_singleq_is_non_eop(struct idpf_queue *rxq, + * + * skb->protocol must be set before this function is called + */ +-static void idpf_rx_singleq_csum(struct idpf_queue *rxq, struct sk_buff *skb, ++static void idpf_rx_singleq_csum(struct idpf_rx_queue *rxq, struct sk_buff *skb, + struct idpf_rx_csum_decoded *csum_bits, + u16 ptype) + { +@@ -647,14 +617,14 @@ static void idpf_rx_singleq_csum(struct idpf_queue *rxq, struct sk_buff *skb, + bool ipv4, ipv6; + + /* check if Rx checksum is enabled */ +- if (unlikely(!(rxq->vport->netdev->features & NETIF_F_RXCSUM))) ++ if (unlikely(!(rxq->netdev->features & NETIF_F_RXCSUM))) + return; + + /* check if HW has decoded the packet and checksum */ + if (unlikely(!(csum_bits->l3l4p))) + return; + +- decoded = rxq->vport->rx_ptype_lkup[ptype]; ++ decoded = rxq->rx_ptype_lkup[ptype]; + if (unlikely(!(decoded.known && decoded.outer_ip))) + return; + +@@ -707,7 +677,7 @@ static void idpf_rx_singleq_csum(struct idpf_queue *rxq, struct sk_buff *skb, + + checksum_fail: + u64_stats_update_begin(&rxq->stats_sync); +- u64_stats_inc(&rxq->q_stats.rx.hw_csum_err); ++ u64_stats_inc(&rxq->q_stats.hw_csum_err); + u64_stats_update_end(&rxq->stats_sync); + } + +@@ -721,9 +691,9 @@ static void idpf_rx_singleq_csum(struct idpf_queue *rxq, struct sk_buff *skb, + * This function only operates on the VIRTCHNL2_RXDID_1_32B_BASE_M base 32byte + * descriptor writeback format. + **/ +-static void idpf_rx_singleq_base_csum(struct idpf_queue *rx_q, ++static void idpf_rx_singleq_base_csum(struct idpf_rx_queue *rx_q, + struct sk_buff *skb, +- union virtchnl2_rx_desc *rx_desc, ++ const union virtchnl2_rx_desc *rx_desc, + u16 ptype) + { + struct idpf_rx_csum_decoded csum_bits; +@@ -761,9 +731,9 @@ static void idpf_rx_singleq_base_csum(struct idpf_queue *rx_q, + * This function only operates on the VIRTCHNL2_RXDID_2_FLEX_SQ_NIC flexible + * descriptor writeback format. + **/ +-static void idpf_rx_singleq_flex_csum(struct idpf_queue *rx_q, ++static void idpf_rx_singleq_flex_csum(struct idpf_rx_queue *rx_q, + struct sk_buff *skb, +- union virtchnl2_rx_desc *rx_desc, ++ const union virtchnl2_rx_desc *rx_desc, + u16 ptype) + { + struct idpf_rx_csum_decoded csum_bits; +@@ -801,14 +771,14 @@ static void idpf_rx_singleq_flex_csum(struct idpf_queue *rx_q, + * This function only operates on the VIRTCHNL2_RXDID_1_32B_BASE_M base 32byte + * descriptor writeback format. + **/ +-static void idpf_rx_singleq_base_hash(struct idpf_queue *rx_q, ++static void idpf_rx_singleq_base_hash(struct idpf_rx_queue *rx_q, + struct sk_buff *skb, +- union virtchnl2_rx_desc *rx_desc, ++ const union virtchnl2_rx_desc *rx_desc, + struct idpf_rx_ptype_decoded *decoded) + { + u64 mask, qw1; + +- if (unlikely(!(rx_q->vport->netdev->features & NETIF_F_RXHASH))) ++ if (unlikely(!(rx_q->netdev->features & NETIF_F_RXHASH))) + return; + + mask = VIRTCHNL2_RX_BASE_DESC_FLTSTAT_RSS_HASH_M; +@@ -831,12 +801,12 @@ static void idpf_rx_singleq_base_hash(struct idpf_queue *rx_q, + * This function only operates on the VIRTCHNL2_RXDID_2_FLEX_SQ_NIC flexible + * descriptor writeback format. + **/ +-static void idpf_rx_singleq_flex_hash(struct idpf_queue *rx_q, ++static void idpf_rx_singleq_flex_hash(struct idpf_rx_queue *rx_q, + struct sk_buff *skb, +- union virtchnl2_rx_desc *rx_desc, ++ const union virtchnl2_rx_desc *rx_desc, + struct idpf_rx_ptype_decoded *decoded) + { +- if (unlikely(!(rx_q->vport->netdev->features & NETIF_F_RXHASH))) ++ if (unlikely(!(rx_q->netdev->features & NETIF_F_RXHASH))) + return; + + if (FIELD_GET(VIRTCHNL2_RX_FLEX_DESC_STATUS0_RSS_VALID_M, +@@ -857,16 +827,16 @@ static void idpf_rx_singleq_flex_hash(struct idpf_queue *rx_q, + * order to populate the hash, checksum, VLAN, protocol, and + * other fields within the skb. + */ +-static void idpf_rx_singleq_process_skb_fields(struct idpf_queue *rx_q, +- struct sk_buff *skb, +- union virtchnl2_rx_desc *rx_desc, +- u16 ptype) ++static void ++idpf_rx_singleq_process_skb_fields(struct idpf_rx_queue *rx_q, ++ struct sk_buff *skb, ++ const union virtchnl2_rx_desc *rx_desc, ++ u16 ptype) + { +- struct idpf_rx_ptype_decoded decoded = +- rx_q->vport->rx_ptype_lkup[ptype]; ++ struct idpf_rx_ptype_decoded decoded = rx_q->rx_ptype_lkup[ptype]; + + /* modifies the skb - consumes the enet header */ +- skb->protocol = eth_type_trans(skb, rx_q->vport->netdev); ++ skb->protocol = eth_type_trans(skb, rx_q->netdev); + + /* Check if we're using base mode descriptor IDs */ + if (rx_q->rxdids == VIRTCHNL2_RXDID_1_32B_BASE_M) { +@@ -878,6 +848,22 @@ static void idpf_rx_singleq_process_skb_fields(struct idpf_queue *rx_q, + } + } + ++/** ++ * idpf_rx_buf_hw_update - Store the new tail and head values ++ * @rxq: queue to bump ++ * @val: new head index ++ */ ++static void idpf_rx_buf_hw_update(struct idpf_rx_queue *rxq, u32 val) ++{ ++ rxq->next_to_use = val; ++ ++ if (unlikely(!rxq->tail)) ++ return; ++ ++ /* writel has an implicit memory barrier */ ++ writel(val, rxq->tail); ++} ++ + /** + * idpf_rx_singleq_buf_hw_alloc_all - Replace used receive buffers + * @rx_q: queue for which the hw buffers are allocated +@@ -885,7 +871,7 @@ static void idpf_rx_singleq_process_skb_fields(struct idpf_queue *rx_q, + * + * Returns false if all allocations were successful, true if any fail + */ +-bool idpf_rx_singleq_buf_hw_alloc_all(struct idpf_queue *rx_q, ++bool idpf_rx_singleq_buf_hw_alloc_all(struct idpf_rx_queue *rx_q, + u16 cleaned_count) + { + struct virtchnl2_singleq_rx_buf_desc *desc; +@@ -895,8 +881,8 @@ bool idpf_rx_singleq_buf_hw_alloc_all(struct idpf_queue *rx_q, + if (!cleaned_count) + return false; + +- desc = IDPF_SINGLEQ_RX_BUF_DESC(rx_q, nta); +- buf = &rx_q->rx_buf.buf[nta]; ++ desc = &rx_q->single_buf[nta]; ++ buf = &rx_q->rx_buf[nta]; + + do { + dma_addr_t addr; +@@ -915,8 +901,8 @@ bool idpf_rx_singleq_buf_hw_alloc_all(struct idpf_queue *rx_q, + buf++; + nta++; + if (unlikely(nta == rx_q->desc_count)) { +- desc = IDPF_SINGLEQ_RX_BUF_DESC(rx_q, 0); +- buf = rx_q->rx_buf.buf; ++ desc = &rx_q->single_buf[0]; ++ buf = rx_q->rx_buf; + nta = 0; + } + +@@ -933,7 +919,6 @@ bool idpf_rx_singleq_buf_hw_alloc_all(struct idpf_queue *rx_q, + + /** + * idpf_rx_singleq_extract_base_fields - Extract fields from the Rx descriptor +- * @rx_q: Rx descriptor queue + * @rx_desc: the descriptor to process + * @fields: storage for extracted values + * +@@ -943,9 +928,9 @@ bool idpf_rx_singleq_buf_hw_alloc_all(struct idpf_queue *rx_q, + * This function only operates on the VIRTCHNL2_RXDID_1_32B_BASE_M base 32byte + * descriptor writeback format. + */ +-static void idpf_rx_singleq_extract_base_fields(struct idpf_queue *rx_q, +- union virtchnl2_rx_desc *rx_desc, +- struct idpf_rx_extracted *fields) ++static void ++idpf_rx_singleq_extract_base_fields(const union virtchnl2_rx_desc *rx_desc, ++ struct idpf_rx_extracted *fields) + { + u64 qword; + +@@ -957,7 +942,6 @@ static void idpf_rx_singleq_extract_base_fields(struct idpf_queue *rx_q, + + /** + * idpf_rx_singleq_extract_flex_fields - Extract fields from the Rx descriptor +- * @rx_q: Rx descriptor queue + * @rx_desc: the descriptor to process + * @fields: storage for extracted values + * +@@ -967,9 +951,9 @@ static void idpf_rx_singleq_extract_base_fields(struct idpf_queue *rx_q, + * This function only operates on the VIRTCHNL2_RXDID_2_FLEX_SQ_NIC flexible + * descriptor writeback format. + */ +-static void idpf_rx_singleq_extract_flex_fields(struct idpf_queue *rx_q, +- union virtchnl2_rx_desc *rx_desc, +- struct idpf_rx_extracted *fields) ++static void ++idpf_rx_singleq_extract_flex_fields(const union virtchnl2_rx_desc *rx_desc, ++ struct idpf_rx_extracted *fields) + { + fields->size = FIELD_GET(VIRTCHNL2_RX_FLEX_DESC_PKT_LEN_M, + le16_to_cpu(rx_desc->flex_nic_wb.pkt_len)); +@@ -984,14 +968,15 @@ static void idpf_rx_singleq_extract_flex_fields(struct idpf_queue *rx_q, + * @fields: storage for extracted values + * + */ +-static void idpf_rx_singleq_extract_fields(struct idpf_queue *rx_q, +- union virtchnl2_rx_desc *rx_desc, +- struct idpf_rx_extracted *fields) ++static void ++idpf_rx_singleq_extract_fields(const struct idpf_rx_queue *rx_q, ++ const union virtchnl2_rx_desc *rx_desc, ++ struct idpf_rx_extracted *fields) + { + if (rx_q->rxdids == VIRTCHNL2_RXDID_1_32B_BASE_M) +- idpf_rx_singleq_extract_base_fields(rx_q, rx_desc, fields); ++ idpf_rx_singleq_extract_base_fields(rx_desc, fields); + else +- idpf_rx_singleq_extract_flex_fields(rx_q, rx_desc, fields); ++ idpf_rx_singleq_extract_flex_fields(rx_desc, fields); + } + + /** +@@ -1001,7 +986,7 @@ static void idpf_rx_singleq_extract_fields(struct idpf_queue *rx_q, + * + * Returns true if there's any budget left (e.g. the clean is finished) + */ +-static int idpf_rx_singleq_clean(struct idpf_queue *rx_q, int budget) ++static int idpf_rx_singleq_clean(struct idpf_rx_queue *rx_q, int budget) + { + unsigned int total_rx_bytes = 0, total_rx_pkts = 0; + struct sk_buff *skb = rx_q->skb; +@@ -1016,7 +1001,7 @@ static int idpf_rx_singleq_clean(struct idpf_queue *rx_q, int budget) + struct idpf_rx_buf *rx_buf; + + /* get the Rx desc from Rx queue based on 'next_to_clean' */ +- rx_desc = IDPF_RX_DESC(rx_q, ntc); ++ rx_desc = &rx_q->rx[ntc]; + + /* status_error_ptype_len will always be zero for unused + * descriptors because it's cleared in cleanup, and overlaps +@@ -1036,7 +1021,7 @@ static int idpf_rx_singleq_clean(struct idpf_queue *rx_q, int budget) + + idpf_rx_singleq_extract_fields(rx_q, rx_desc, &fields); + +- rx_buf = &rx_q->rx_buf.buf[ntc]; ++ rx_buf = &rx_q->rx_buf[ntc]; + if (!fields.size) { + idpf_rx_put_page(rx_buf); + goto skip_data; +@@ -1058,7 +1043,7 @@ static int idpf_rx_singleq_clean(struct idpf_queue *rx_q, int budget) + cleaned_count++; + + /* skip if it is non EOP desc */ +- if (idpf_rx_singleq_is_non_eop(rx_q, rx_desc, skb, ntc)) ++ if (idpf_rx_singleq_is_non_eop(rx_desc)) + continue; + + #define IDPF_RXD_ERR_S FIELD_PREP(VIRTCHNL2_RX_BASE_DESC_QW1_ERROR_M, \ +@@ -1084,7 +1069,7 @@ static int idpf_rx_singleq_clean(struct idpf_queue *rx_q, int budget) + rx_desc, fields.rx_ptype); + + /* send completed skb up the stack */ +- napi_gro_receive(&rx_q->q_vector->napi, skb); ++ napi_gro_receive(rx_q->pp->p.napi, skb); + skb = NULL; + + /* update budget accounting */ +@@ -1099,8 +1084,8 @@ static int idpf_rx_singleq_clean(struct idpf_queue *rx_q, int budget) + failure = idpf_rx_singleq_buf_hw_alloc_all(rx_q, cleaned_count); + + u64_stats_update_begin(&rx_q->stats_sync); +- u64_stats_add(&rx_q->q_stats.rx.packets, total_rx_pkts); +- u64_stats_add(&rx_q->q_stats.rx.bytes, total_rx_bytes); ++ u64_stats_add(&rx_q->q_stats.packets, total_rx_pkts); ++ u64_stats_add(&rx_q->q_stats.bytes, total_rx_bytes); + u64_stats_update_end(&rx_q->stats_sync); + + /* guarantee a trip back through this routine if there was a failure */ +@@ -1127,7 +1112,7 @@ static bool idpf_rx_singleq_clean_all(struct idpf_q_vector *q_vec, int budget, + */ + budget_per_q = num_rxq ? max(budget / num_rxq, 1) : 0; + for (i = 0; i < num_rxq; i++) { +- struct idpf_queue *rxq = q_vec->rx[i]; ++ struct idpf_rx_queue *rxq = q_vec->rx[i]; + int pkts_cleaned_per_q; + + pkts_cleaned_per_q = idpf_rx_singleq_clean(rxq, budget_per_q); +diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c b/drivers/net/ethernet/intel/idpf/idpf_txrx.c +index 20ca04320d4bde..9b7e67d0f38be9 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c ++++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c +@@ -4,6 +4,9 @@ + #include "idpf.h" + #include "idpf_virtchnl.h" + ++static bool idpf_chk_linearize(struct sk_buff *skb, unsigned int max_bufs, ++ unsigned int count); ++ + /** + * idpf_buf_lifo_push - push a buffer pointer onto stack + * @stack: pointer to stack struct +@@ -60,7 +63,8 @@ void idpf_tx_timeout(struct net_device *netdev, unsigned int txqueue) + * @tx_q: the queue that owns the buffer + * @tx_buf: the buffer to free + */ +-static void idpf_tx_buf_rel(struct idpf_queue *tx_q, struct idpf_tx_buf *tx_buf) ++static void idpf_tx_buf_rel(struct idpf_tx_queue *tx_q, ++ struct idpf_tx_buf *tx_buf) + { + if (tx_buf->skb) { + if (dma_unmap_len(tx_buf, len)) +@@ -86,8 +90,9 @@ static void idpf_tx_buf_rel(struct idpf_queue *tx_q, struct idpf_tx_buf *tx_buf) + * idpf_tx_buf_rel_all - Free any empty Tx buffers + * @txq: queue to be cleaned + */ +-static void idpf_tx_buf_rel_all(struct idpf_queue *txq) ++static void idpf_tx_buf_rel_all(struct idpf_tx_queue *txq) + { ++ struct idpf_buf_lifo *buf_stack; + u16 i; + + /* Buffers already cleared, nothing to do */ +@@ -101,38 +106,57 @@ static void idpf_tx_buf_rel_all(struct idpf_queue *txq) + kfree(txq->tx_buf); + txq->tx_buf = NULL; + +- if (!txq->buf_stack.bufs) ++ if (!idpf_queue_has(FLOW_SCH_EN, txq)) ++ return; ++ ++ buf_stack = &txq->stash->buf_stack; ++ if (!buf_stack->bufs) + return; + +- for (i = 0; i < txq->buf_stack.size; i++) +- kfree(txq->buf_stack.bufs[i]); ++ for (i = 0; i < buf_stack->size; i++) ++ kfree(buf_stack->bufs[i]); + +- kfree(txq->buf_stack.bufs); +- txq->buf_stack.bufs = NULL; ++ kfree(buf_stack->bufs); ++ buf_stack->bufs = NULL; + } + + /** + * idpf_tx_desc_rel - Free Tx resources per queue + * @txq: Tx descriptor ring for a specific queue +- * @bufq: buffer q or completion q + * + * Free all transmit software resources + */ +-static void idpf_tx_desc_rel(struct idpf_queue *txq, bool bufq) ++static void idpf_tx_desc_rel(struct idpf_tx_queue *txq) + { +- if (bufq) +- idpf_tx_buf_rel_all(txq); ++ idpf_tx_buf_rel_all(txq); + + if (!txq->desc_ring) + return; + + dmam_free_coherent(txq->dev, txq->size, txq->desc_ring, txq->dma); + txq->desc_ring = NULL; +- txq->next_to_alloc = 0; + txq->next_to_use = 0; + txq->next_to_clean = 0; + } + ++/** ++ * idpf_compl_desc_rel - Free completion resources per queue ++ * @complq: completion queue ++ * ++ * Free all completion software resources. ++ */ ++static void idpf_compl_desc_rel(struct idpf_compl_queue *complq) ++{ ++ if (!complq->comp) ++ return; ++ ++ dma_free_coherent(complq->netdev->dev.parent, complq->size, ++ complq->comp, complq->dma); ++ complq->comp = NULL; ++ complq->next_to_use = 0; ++ complq->next_to_clean = 0; ++} ++ + /** + * idpf_tx_desc_rel_all - Free Tx Resources for All Queues + * @vport: virtual port structure +@@ -150,10 +174,10 @@ static void idpf_tx_desc_rel_all(struct idpf_vport *vport) + struct idpf_txq_group *txq_grp = &vport->txq_grps[i]; + + for (j = 0; j < txq_grp->num_txq; j++) +- idpf_tx_desc_rel(txq_grp->txqs[j], true); ++ idpf_tx_desc_rel(txq_grp->txqs[j]); + + if (idpf_is_queue_model_split(vport->txq_model)) +- idpf_tx_desc_rel(txq_grp->complq, false); ++ idpf_compl_desc_rel(txq_grp->complq); + } + } + +@@ -163,8 +187,9 @@ static void idpf_tx_desc_rel_all(struct idpf_vport *vport) + * + * Returns 0 on success, negative on failure + */ +-static int idpf_tx_buf_alloc_all(struct idpf_queue *tx_q) ++static int idpf_tx_buf_alloc_all(struct idpf_tx_queue *tx_q) + { ++ struct idpf_buf_lifo *buf_stack; + int buf_size; + int i; + +@@ -180,22 +205,26 @@ static int idpf_tx_buf_alloc_all(struct idpf_queue *tx_q) + for (i = 0; i < tx_q->desc_count; i++) + tx_q->tx_buf[i].compl_tag = IDPF_SPLITQ_TX_INVAL_COMPL_TAG; + ++ if (!idpf_queue_has(FLOW_SCH_EN, tx_q)) ++ return 0; ++ ++ buf_stack = &tx_q->stash->buf_stack; ++ + /* Initialize tx buf stack for out-of-order completions if + * flow scheduling offload is enabled + */ +- tx_q->buf_stack.bufs = +- kcalloc(tx_q->desc_count, sizeof(struct idpf_tx_stash *), +- GFP_KERNEL); +- if (!tx_q->buf_stack.bufs) ++ buf_stack->bufs = kcalloc(tx_q->desc_count, sizeof(*buf_stack->bufs), ++ GFP_KERNEL); ++ if (!buf_stack->bufs) + return -ENOMEM; + +- tx_q->buf_stack.size = tx_q->desc_count; +- tx_q->buf_stack.top = tx_q->desc_count; ++ buf_stack->size = tx_q->desc_count; ++ buf_stack->top = tx_q->desc_count; + + for (i = 0; i < tx_q->desc_count; i++) { +- tx_q->buf_stack.bufs[i] = kzalloc(sizeof(*tx_q->buf_stack.bufs[i]), +- GFP_KERNEL); +- if (!tx_q->buf_stack.bufs[i]) ++ buf_stack->bufs[i] = kzalloc(sizeof(*buf_stack->bufs[i]), ++ GFP_KERNEL); ++ if (!buf_stack->bufs[i]) + return -ENOMEM; + } + +@@ -204,28 +233,22 @@ static int idpf_tx_buf_alloc_all(struct idpf_queue *tx_q) + + /** + * idpf_tx_desc_alloc - Allocate the Tx descriptors ++ * @vport: vport to allocate resources for + * @tx_q: the tx ring to set up +- * @bufq: buffer or completion queue + * + * Returns 0 on success, negative on failure + */ +-static int idpf_tx_desc_alloc(struct idpf_queue *tx_q, bool bufq) ++static int idpf_tx_desc_alloc(const struct idpf_vport *vport, ++ struct idpf_tx_queue *tx_q) + { + struct device *dev = tx_q->dev; +- u32 desc_sz; + int err; + +- if (bufq) { +- err = idpf_tx_buf_alloc_all(tx_q); +- if (err) +- goto err_alloc; +- +- desc_sz = sizeof(struct idpf_base_tx_desc); +- } else { +- desc_sz = sizeof(struct idpf_splitq_tx_compl_desc); +- } ++ err = idpf_tx_buf_alloc_all(tx_q); ++ if (err) ++ goto err_alloc; + +- tx_q->size = tx_q->desc_count * desc_sz; ++ tx_q->size = tx_q->desc_count * sizeof(*tx_q->base_tx); + + /* Allocate descriptors also round up to nearest 4K */ + tx_q->size = ALIGN(tx_q->size, 4096); +@@ -238,19 +261,43 @@ static int idpf_tx_desc_alloc(struct idpf_queue *tx_q, bool bufq) + goto err_alloc; + } + +- tx_q->next_to_alloc = 0; + tx_q->next_to_use = 0; + tx_q->next_to_clean = 0; +- set_bit(__IDPF_Q_GEN_CHK, tx_q->flags); ++ idpf_queue_set(GEN_CHK, tx_q); + + return 0; + + err_alloc: +- idpf_tx_desc_rel(tx_q, bufq); ++ idpf_tx_desc_rel(tx_q); + + return err; + } + ++/** ++ * idpf_compl_desc_alloc - allocate completion descriptors ++ * @vport: vport to allocate resources for ++ * @complq: completion queue to set up ++ * ++ * Return: 0 on success, -errno on failure. ++ */ ++static int idpf_compl_desc_alloc(const struct idpf_vport *vport, ++ struct idpf_compl_queue *complq) ++{ ++ complq->size = array_size(complq->desc_count, sizeof(*complq->comp)); ++ ++ complq->comp = dma_alloc_coherent(complq->netdev->dev.parent, ++ complq->size, &complq->dma, ++ GFP_KERNEL); ++ if (!complq->comp) ++ return -ENOMEM; ++ ++ complq->next_to_use = 0; ++ complq->next_to_clean = 0; ++ idpf_queue_set(GEN_CHK, complq); ++ ++ return 0; ++} ++ + /** + * idpf_tx_desc_alloc_all - allocate all queues Tx resources + * @vport: virtual port private structure +@@ -259,7 +306,6 @@ static int idpf_tx_desc_alloc(struct idpf_queue *tx_q, bool bufq) + */ + static int idpf_tx_desc_alloc_all(struct idpf_vport *vport) + { +- struct device *dev = &vport->adapter->pdev->dev; + int err = 0; + int i, j; + +@@ -268,13 +314,14 @@ static int idpf_tx_desc_alloc_all(struct idpf_vport *vport) + */ + for (i = 0; i < vport->num_txq_grp; i++) { + for (j = 0; j < vport->txq_grps[i].num_txq; j++) { +- struct idpf_queue *txq = vport->txq_grps[i].txqs[j]; ++ struct idpf_tx_queue *txq = vport->txq_grps[i].txqs[j]; + u8 gen_bits = 0; + u16 bufidx_mask; + +- err = idpf_tx_desc_alloc(txq, true); ++ err = idpf_tx_desc_alloc(vport, txq); + if (err) { +- dev_err(dev, "Allocation for Tx Queue %u failed\n", ++ pci_err(vport->adapter->pdev, ++ "Allocation for Tx Queue %u failed\n", + i); + goto err_out; + } +@@ -312,9 +359,10 @@ static int idpf_tx_desc_alloc_all(struct idpf_vport *vport) + continue; + + /* Setup completion queues */ +- err = idpf_tx_desc_alloc(vport->txq_grps[i].complq, false); ++ err = idpf_compl_desc_alloc(vport, vport->txq_grps[i].complq); + if (err) { +- dev_err(dev, "Allocation for Tx Completion Queue %u failed\n", ++ pci_err(vport->adapter->pdev, ++ "Allocation for Tx Completion Queue %u failed\n", + i); + goto err_out; + } +@@ -329,15 +377,14 @@ static int idpf_tx_desc_alloc_all(struct idpf_vport *vport) + + /** + * idpf_rx_page_rel - Release an rx buffer page +- * @rxq: the queue that owns the buffer + * @rx_buf: the buffer to free + */ +-static void idpf_rx_page_rel(struct idpf_queue *rxq, struct idpf_rx_buf *rx_buf) ++static void idpf_rx_page_rel(struct idpf_rx_buf *rx_buf) + { + if (unlikely(!rx_buf->page)) + return; + +- page_pool_put_full_page(rxq->pp, rx_buf->page, false); ++ page_pool_put_full_page(rx_buf->page->pp, rx_buf->page, false); + + rx_buf->page = NULL; + rx_buf->page_offset = 0; +@@ -345,54 +392,72 @@ static void idpf_rx_page_rel(struct idpf_queue *rxq, struct idpf_rx_buf *rx_buf) + + /** + * idpf_rx_hdr_buf_rel_all - Release header buffer memory +- * @rxq: queue to use ++ * @bufq: queue to use ++ * @dev: device to free DMA memory + */ +-static void idpf_rx_hdr_buf_rel_all(struct idpf_queue *rxq) ++static void idpf_rx_hdr_buf_rel_all(struct idpf_buf_queue *bufq, ++ struct device *dev) + { +- struct idpf_adapter *adapter = rxq->vport->adapter; +- +- dma_free_coherent(&adapter->pdev->dev, +- rxq->desc_count * IDPF_HDR_BUF_SIZE, +- rxq->rx_buf.hdr_buf_va, +- rxq->rx_buf.hdr_buf_pa); +- rxq->rx_buf.hdr_buf_va = NULL; ++ dma_free_coherent(dev, bufq->desc_count * IDPF_HDR_BUF_SIZE, ++ bufq->rx_buf.hdr_buf_va, bufq->rx_buf.hdr_buf_pa); ++ bufq->rx_buf.hdr_buf_va = NULL; + } + + /** +- * idpf_rx_buf_rel_all - Free all Rx buffer resources for a queue +- * @rxq: queue to be cleaned ++ * idpf_rx_buf_rel_bufq - Free all Rx buffer resources for a buffer queue ++ * @bufq: queue to be cleaned ++ * @dev: device to free DMA memory + */ +-static void idpf_rx_buf_rel_all(struct idpf_queue *rxq) ++static void idpf_rx_buf_rel_bufq(struct idpf_buf_queue *bufq, ++ struct device *dev) + { +- u16 i; +- + /* queue already cleared, nothing to do */ +- if (!rxq->rx_buf.buf) ++ if (!bufq->rx_buf.buf) + return; + + /* Free all the bufs allocated and given to hw on Rx queue */ +- for (i = 0; i < rxq->desc_count; i++) +- idpf_rx_page_rel(rxq, &rxq->rx_buf.buf[i]); ++ for (u32 i = 0; i < bufq->desc_count; i++) ++ idpf_rx_page_rel(&bufq->rx_buf.buf[i]); ++ ++ if (idpf_queue_has(HSPLIT_EN, bufq)) ++ idpf_rx_hdr_buf_rel_all(bufq, dev); + +- if (rxq->rx_hsplit_en) +- idpf_rx_hdr_buf_rel_all(rxq); ++ page_pool_destroy(bufq->pp); ++ bufq->pp = NULL; ++ ++ kfree(bufq->rx_buf.buf); ++ bufq->rx_buf.buf = NULL; ++} ++ ++/** ++ * idpf_rx_buf_rel_all - Free all Rx buffer resources for a receive queue ++ * @rxq: queue to be cleaned ++ */ ++static void idpf_rx_buf_rel_all(struct idpf_rx_queue *rxq) ++{ ++ if (!rxq->rx_buf) ++ return; ++ ++ for (u32 i = 0; i < rxq->desc_count; i++) ++ idpf_rx_page_rel(&rxq->rx_buf[i]); + + page_pool_destroy(rxq->pp); + rxq->pp = NULL; + +- kfree(rxq->rx_buf.buf); +- rxq->rx_buf.buf = NULL; ++ kfree(rxq->rx_buf); ++ rxq->rx_buf = NULL; + } + + /** + * idpf_rx_desc_rel - Free a specific Rx q resources + * @rxq: queue to clean the resources from +- * @bufq: buffer q or completion q +- * @q_model: single or split q model ++ * @dev: device to free DMA memory ++ * @model: single or split queue model + * + * Free a specific rx queue resources + */ +-static void idpf_rx_desc_rel(struct idpf_queue *rxq, bool bufq, s32 q_model) ++static void idpf_rx_desc_rel(struct idpf_rx_queue *rxq, struct device *dev, ++ u32 model) + { + if (!rxq) + return; +@@ -402,7 +467,7 @@ static void idpf_rx_desc_rel(struct idpf_queue *rxq, bool bufq, s32 q_model) + rxq->skb = NULL; + } + +- if (bufq || !idpf_is_queue_model_split(q_model)) ++ if (!idpf_is_queue_model_split(model)) + idpf_rx_buf_rel_all(rxq); + + rxq->next_to_alloc = 0; +@@ -411,10 +476,34 @@ static void idpf_rx_desc_rel(struct idpf_queue *rxq, bool bufq, s32 q_model) + if (!rxq->desc_ring) + return; + +- dmam_free_coherent(rxq->dev, rxq->size, rxq->desc_ring, rxq->dma); ++ dmam_free_coherent(dev, rxq->size, rxq->desc_ring, rxq->dma); + rxq->desc_ring = NULL; + } + ++/** ++ * idpf_rx_desc_rel_bufq - free buffer queue resources ++ * @bufq: buffer queue to clean the resources from ++ * @dev: device to free DMA memory ++ */ ++static void idpf_rx_desc_rel_bufq(struct idpf_buf_queue *bufq, ++ struct device *dev) ++{ ++ if (!bufq) ++ return; ++ ++ idpf_rx_buf_rel_bufq(bufq, dev); ++ ++ bufq->next_to_alloc = 0; ++ bufq->next_to_clean = 0; ++ bufq->next_to_use = 0; ++ ++ if (!bufq->split_buf) ++ return; ++ ++ dma_free_coherent(dev, bufq->size, bufq->split_buf, bufq->dma); ++ bufq->split_buf = NULL; ++} ++ + /** + * idpf_rx_desc_rel_all - Free Rx Resources for All Queues + * @vport: virtual port structure +@@ -423,6 +512,7 @@ static void idpf_rx_desc_rel(struct idpf_queue *rxq, bool bufq, s32 q_model) + */ + static void idpf_rx_desc_rel_all(struct idpf_vport *vport) + { ++ struct device *dev = &vport->adapter->pdev->dev; + struct idpf_rxq_group *rx_qgrp; + u16 num_rxq; + int i, j; +@@ -435,15 +525,15 @@ static void idpf_rx_desc_rel_all(struct idpf_vport *vport) + + if (!idpf_is_queue_model_split(vport->rxq_model)) { + for (j = 0; j < rx_qgrp->singleq.num_rxq; j++) +- idpf_rx_desc_rel(rx_qgrp->singleq.rxqs[j], +- false, vport->rxq_model); ++ idpf_rx_desc_rel(rx_qgrp->singleq.rxqs[j], dev, ++ VIRTCHNL2_QUEUE_MODEL_SINGLE); + continue; + } + + num_rxq = rx_qgrp->splitq.num_rxq_sets; + for (j = 0; j < num_rxq; j++) + idpf_rx_desc_rel(&rx_qgrp->splitq.rxq_sets[j]->rxq, +- false, vport->rxq_model); ++ dev, VIRTCHNL2_QUEUE_MODEL_SPLIT); + + if (!rx_qgrp->splitq.bufq_sets) + continue; +@@ -452,44 +542,40 @@ static void idpf_rx_desc_rel_all(struct idpf_vport *vport) + struct idpf_bufq_set *bufq_set = + &rx_qgrp->splitq.bufq_sets[j]; + +- idpf_rx_desc_rel(&bufq_set->bufq, true, +- vport->rxq_model); ++ idpf_rx_desc_rel_bufq(&bufq_set->bufq, dev); + } + } + } + + /** + * idpf_rx_buf_hw_update - Store the new tail and head values +- * @rxq: queue to bump ++ * @bufq: queue to bump + * @val: new head index + */ +-void idpf_rx_buf_hw_update(struct idpf_queue *rxq, u32 val) ++static void idpf_rx_buf_hw_update(struct idpf_buf_queue *bufq, u32 val) + { +- rxq->next_to_use = val; ++ bufq->next_to_use = val; + +- if (unlikely(!rxq->tail)) ++ if (unlikely(!bufq->tail)) + return; + + /* writel has an implicit memory barrier */ +- writel(val, rxq->tail); ++ writel(val, bufq->tail); + } + + /** + * idpf_rx_hdr_buf_alloc_all - Allocate memory for header buffers +- * @rxq: ring to use ++ * @bufq: ring to use + * + * Returns 0 on success, negative on failure. + */ +-static int idpf_rx_hdr_buf_alloc_all(struct idpf_queue *rxq) ++static int idpf_rx_hdr_buf_alloc_all(struct idpf_buf_queue *bufq) + { +- struct idpf_adapter *adapter = rxq->vport->adapter; +- +- rxq->rx_buf.hdr_buf_va = +- dma_alloc_coherent(&adapter->pdev->dev, +- IDPF_HDR_BUF_SIZE * rxq->desc_count, +- &rxq->rx_buf.hdr_buf_pa, +- GFP_KERNEL); +- if (!rxq->rx_buf.hdr_buf_va) ++ bufq->rx_buf.hdr_buf_va = ++ dma_alloc_coherent(bufq->q_vector->vport->netdev->dev.parent, ++ IDPF_HDR_BUF_SIZE * bufq->desc_count, ++ &bufq->rx_buf.hdr_buf_pa, GFP_KERNEL); ++ if (!bufq->rx_buf.hdr_buf_va) + return -ENOMEM; + + return 0; +@@ -502,19 +588,20 @@ static int idpf_rx_hdr_buf_alloc_all(struct idpf_queue *rxq) + */ + static void idpf_rx_post_buf_refill(struct idpf_sw_queue *refillq, u16 buf_id) + { +- u16 nta = refillq->next_to_alloc; ++ u32 nta = refillq->next_to_use; + + /* store the buffer ID and the SW maintained GEN bit to the refillq */ + refillq->ring[nta] = + FIELD_PREP(IDPF_RX_BI_BUFID_M, buf_id) | + FIELD_PREP(IDPF_RX_BI_GEN_M, +- test_bit(__IDPF_Q_GEN_CHK, refillq->flags)); ++ idpf_queue_has(GEN_CHK, refillq)); + + if (unlikely(++nta == refillq->desc_count)) { + nta = 0; +- change_bit(__IDPF_Q_GEN_CHK, refillq->flags); ++ idpf_queue_change(GEN_CHK, refillq); + } +- refillq->next_to_alloc = nta; ++ ++ refillq->next_to_use = nta; + } + + /** +@@ -524,21 +611,20 @@ static void idpf_rx_post_buf_refill(struct idpf_sw_queue *refillq, u16 buf_id) + * + * Returns false if buffer could not be allocated, true otherwise. + */ +-static bool idpf_rx_post_buf_desc(struct idpf_queue *bufq, u16 buf_id) ++static bool idpf_rx_post_buf_desc(struct idpf_buf_queue *bufq, u16 buf_id) + { + struct virtchnl2_splitq_rx_buf_desc *splitq_rx_desc = NULL; + u16 nta = bufq->next_to_alloc; + struct idpf_rx_buf *buf; + dma_addr_t addr; + +- splitq_rx_desc = IDPF_SPLITQ_RX_BUF_DESC(bufq, nta); ++ splitq_rx_desc = &bufq->split_buf[nta]; + buf = &bufq->rx_buf.buf[buf_id]; + +- if (bufq->rx_hsplit_en) { ++ if (idpf_queue_has(HSPLIT_EN, bufq)) + splitq_rx_desc->hdr_addr = + cpu_to_le64(bufq->rx_buf.hdr_buf_pa + + (u32)buf_id * IDPF_HDR_BUF_SIZE); +- } + + addr = idpf_alloc_page(bufq->pp, buf, bufq->rx_buf_size); + if (unlikely(addr == DMA_MAPPING_ERROR)) +@@ -562,7 +648,8 @@ static bool idpf_rx_post_buf_desc(struct idpf_queue *bufq, u16 buf_id) + * + * Returns true if @working_set bufs were posted successfully, false otherwise. + */ +-static bool idpf_rx_post_init_bufs(struct idpf_queue *bufq, u16 working_set) ++static bool idpf_rx_post_init_bufs(struct idpf_buf_queue *bufq, ++ u16 working_set) + { + int i; + +@@ -571,26 +658,28 @@ static bool idpf_rx_post_init_bufs(struct idpf_queue *bufq, u16 working_set) + return false; + } + +- idpf_rx_buf_hw_update(bufq, +- bufq->next_to_alloc & ~(bufq->rx_buf_stride - 1)); ++ idpf_rx_buf_hw_update(bufq, ALIGN_DOWN(bufq->next_to_alloc, ++ IDPF_RX_BUF_STRIDE)); + + return true; + } + + /** + * idpf_rx_create_page_pool - Create a page pool +- * @rxbufq: RX queue to create page pool for ++ * @napi: NAPI of the associated queue vector ++ * @count: queue descriptor count + * + * Returns &page_pool on success, casted -errno on failure + */ +-static struct page_pool *idpf_rx_create_page_pool(struct idpf_queue *rxbufq) ++static struct page_pool *idpf_rx_create_page_pool(struct napi_struct *napi, ++ u32 count) + { + struct page_pool_params pp = { + .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV, + .order = 0, +- .pool_size = rxbufq->desc_count, ++ .pool_size = count, + .nid = NUMA_NO_NODE, +- .dev = rxbufq->vport->netdev->dev.parent, ++ .dev = napi->dev->dev.parent, + .max_len = PAGE_SIZE, + .dma_dir = DMA_FROM_DEVICE, + .offset = 0, +@@ -599,15 +688,58 @@ static struct page_pool *idpf_rx_create_page_pool(struct idpf_queue *rxbufq) + return page_pool_create(&pp); + } + ++/** ++ * idpf_rx_buf_alloc_singleq - Allocate memory for all buffer resources ++ * @rxq: queue for which the buffers are allocated ++ * ++ * Return: 0 on success, -ENOMEM on failure. ++ */ ++static int idpf_rx_buf_alloc_singleq(struct idpf_rx_queue *rxq) ++{ ++ rxq->rx_buf = kcalloc(rxq->desc_count, sizeof(*rxq->rx_buf), ++ GFP_KERNEL); ++ if (!rxq->rx_buf) ++ return -ENOMEM; ++ ++ if (idpf_rx_singleq_buf_hw_alloc_all(rxq, rxq->desc_count - 1)) ++ goto err; ++ ++ return 0; ++ ++err: ++ idpf_rx_buf_rel_all(rxq); ++ ++ return -ENOMEM; ++} ++ ++/** ++ * idpf_rx_bufs_init_singleq - Initialize page pool and allocate Rx bufs ++ * @rxq: buffer queue to create page pool for ++ * ++ * Return: 0 on success, -errno on failure. ++ */ ++static int idpf_rx_bufs_init_singleq(struct idpf_rx_queue *rxq) ++{ ++ struct page_pool *pool; ++ ++ pool = idpf_rx_create_page_pool(&rxq->q_vector->napi, rxq->desc_count); ++ if (IS_ERR(pool)) ++ return PTR_ERR(pool); ++ ++ rxq->pp = pool; ++ ++ return idpf_rx_buf_alloc_singleq(rxq); ++} ++ + /** + * idpf_rx_buf_alloc_all - Allocate memory for all buffer resources +- * @rxbufq: queue for which the buffers are allocated; equivalent to +- * rxq when operating in singleq mode ++ * @rxbufq: queue for which the buffers are allocated + * + * Returns 0 on success, negative on failure + */ +-static int idpf_rx_buf_alloc_all(struct idpf_queue *rxbufq) ++static int idpf_rx_buf_alloc_all(struct idpf_buf_queue *rxbufq) + { ++ struct device *dev = rxbufq->q_vector->vport->netdev->dev.parent; + int err = 0; + + /* Allocate book keeping buffers */ +@@ -618,48 +750,41 @@ static int idpf_rx_buf_alloc_all(struct idpf_queue *rxbufq) + goto rx_buf_alloc_all_out; + } + +- if (rxbufq->rx_hsplit_en) { ++ if (idpf_queue_has(HSPLIT_EN, rxbufq)) { + err = idpf_rx_hdr_buf_alloc_all(rxbufq); + if (err) + goto rx_buf_alloc_all_out; + } + + /* Allocate buffers to be given to HW. */ +- if (idpf_is_queue_model_split(rxbufq->vport->rxq_model)) { +- int working_set = IDPF_RX_BUFQ_WORKING_SET(rxbufq); +- +- if (!idpf_rx_post_init_bufs(rxbufq, working_set)) +- err = -ENOMEM; +- } else { +- if (idpf_rx_singleq_buf_hw_alloc_all(rxbufq, +- rxbufq->desc_count - 1)) +- err = -ENOMEM; +- } ++ if (!idpf_rx_post_init_bufs(rxbufq, IDPF_RX_BUFQ_WORKING_SET(rxbufq))) ++ err = -ENOMEM; + + rx_buf_alloc_all_out: + if (err) +- idpf_rx_buf_rel_all(rxbufq); ++ idpf_rx_buf_rel_bufq(rxbufq, dev); + + return err; + } + + /** + * idpf_rx_bufs_init - Initialize page pool, allocate rx bufs, and post to HW +- * @rxbufq: RX queue to create page pool for ++ * @bufq: buffer queue to create page pool for + * + * Returns 0 on success, negative on failure + */ +-static int idpf_rx_bufs_init(struct idpf_queue *rxbufq) ++static int idpf_rx_bufs_init(struct idpf_buf_queue *bufq) + { + struct page_pool *pool; + +- pool = idpf_rx_create_page_pool(rxbufq); ++ pool = idpf_rx_create_page_pool(&bufq->q_vector->napi, ++ bufq->desc_count); + if (IS_ERR(pool)) + return PTR_ERR(pool); + +- rxbufq->pp = pool; ++ bufq->pp = pool; + +- return idpf_rx_buf_alloc_all(rxbufq); ++ return idpf_rx_buf_alloc_all(bufq); + } + + /** +@@ -671,7 +796,6 @@ static int idpf_rx_bufs_init(struct idpf_queue *rxbufq) + int idpf_rx_bufs_init_all(struct idpf_vport *vport) + { + struct idpf_rxq_group *rx_qgrp; +- struct idpf_queue *q; + int i, j, err; + + for (i = 0; i < vport->num_rxq_grp; i++) { +@@ -682,8 +806,10 @@ int idpf_rx_bufs_init_all(struct idpf_vport *vport) + int num_rxq = rx_qgrp->singleq.num_rxq; + + for (j = 0; j < num_rxq; j++) { ++ struct idpf_rx_queue *q; ++ + q = rx_qgrp->singleq.rxqs[j]; +- err = idpf_rx_bufs_init(q); ++ err = idpf_rx_bufs_init_singleq(q); + if (err) + return err; + } +@@ -693,6 +819,8 @@ int idpf_rx_bufs_init_all(struct idpf_vport *vport) + + /* Otherwise, allocate bufs for the buffer queues */ + for (j = 0; j < vport->num_bufqs_per_qgrp; j++) { ++ struct idpf_buf_queue *q; ++ + q = &rx_qgrp->splitq.bufq_sets[j].bufq; + err = idpf_rx_bufs_init(q); + if (err) +@@ -705,22 +833,17 @@ int idpf_rx_bufs_init_all(struct idpf_vport *vport) + + /** + * idpf_rx_desc_alloc - Allocate queue Rx resources ++ * @vport: vport to allocate resources for + * @rxq: Rx queue for which the resources are setup +- * @bufq: buffer or completion queue +- * @q_model: single or split queue model + * + * Returns 0 on success, negative on failure + */ +-static int idpf_rx_desc_alloc(struct idpf_queue *rxq, bool bufq, s32 q_model) ++static int idpf_rx_desc_alloc(const struct idpf_vport *vport, ++ struct idpf_rx_queue *rxq) + { +- struct device *dev = rxq->dev; ++ struct device *dev = &vport->adapter->pdev->dev; + +- if (bufq) +- rxq->size = rxq->desc_count * +- sizeof(struct virtchnl2_splitq_rx_buf_desc); +- else +- rxq->size = rxq->desc_count * +- sizeof(union virtchnl2_rx_desc); ++ rxq->size = rxq->desc_count * sizeof(union virtchnl2_rx_desc); + + /* Allocate descriptors and also round up to nearest 4K */ + rxq->size = ALIGN(rxq->size, 4096); +@@ -735,7 +858,35 @@ static int idpf_rx_desc_alloc(struct idpf_queue *rxq, bool bufq, s32 q_model) + rxq->next_to_alloc = 0; + rxq->next_to_clean = 0; + rxq->next_to_use = 0; +- set_bit(__IDPF_Q_GEN_CHK, rxq->flags); ++ idpf_queue_set(GEN_CHK, rxq); ++ ++ return 0; ++} ++ ++/** ++ * idpf_bufq_desc_alloc - Allocate buffer queue descriptor ring ++ * @vport: vport to allocate resources for ++ * @bufq: buffer queue for which the resources are set up ++ * ++ * Return: 0 on success, -ENOMEM on failure. ++ */ ++static int idpf_bufq_desc_alloc(const struct idpf_vport *vport, ++ struct idpf_buf_queue *bufq) ++{ ++ struct device *dev = &vport->adapter->pdev->dev; ++ ++ bufq->size = array_size(bufq->desc_count, sizeof(*bufq->split_buf)); ++ ++ bufq->split_buf = dma_alloc_coherent(dev, bufq->size, &bufq->dma, ++ GFP_KERNEL); ++ if (!bufq->split_buf) ++ return -ENOMEM; ++ ++ bufq->next_to_alloc = 0; ++ bufq->next_to_clean = 0; ++ bufq->next_to_use = 0; ++ ++ idpf_queue_set(GEN_CHK, bufq); + + return 0; + } +@@ -748,9 +899,7 @@ static int idpf_rx_desc_alloc(struct idpf_queue *rxq, bool bufq, s32 q_model) + */ + static int idpf_rx_desc_alloc_all(struct idpf_vport *vport) + { +- struct device *dev = &vport->adapter->pdev->dev; + struct idpf_rxq_group *rx_qgrp; +- struct idpf_queue *q; + int i, j, err; + u16 num_rxq; + +@@ -762,13 +911,17 @@ static int idpf_rx_desc_alloc_all(struct idpf_vport *vport) + num_rxq = rx_qgrp->singleq.num_rxq; + + for (j = 0; j < num_rxq; j++) { ++ struct idpf_rx_queue *q; ++ + if (idpf_is_queue_model_split(vport->rxq_model)) + q = &rx_qgrp->splitq.rxq_sets[j]->rxq; + else + q = rx_qgrp->singleq.rxqs[j]; +- err = idpf_rx_desc_alloc(q, false, vport->rxq_model); ++ ++ err = idpf_rx_desc_alloc(vport, q); + if (err) { +- dev_err(dev, "Memory allocation for Rx Queue %u failed\n", ++ pci_err(vport->adapter->pdev, ++ "Memory allocation for Rx Queue %u failed\n", + i); + goto err_out; + } +@@ -778,10 +931,14 @@ static int idpf_rx_desc_alloc_all(struct idpf_vport *vport) + continue; + + for (j = 0; j < vport->num_bufqs_per_qgrp; j++) { ++ struct idpf_buf_queue *q; ++ + q = &rx_qgrp->splitq.bufq_sets[j].bufq; +- err = idpf_rx_desc_alloc(q, true, vport->rxq_model); ++ ++ err = idpf_bufq_desc_alloc(vport, q); + if (err) { +- dev_err(dev, "Memory allocation for Rx Buffer Queue %u failed\n", ++ pci_err(vport->adapter->pdev, ++ "Memory allocation for Rx Buffer Queue %u failed\n", + i); + goto err_out; + } +@@ -802,11 +959,16 @@ static int idpf_rx_desc_alloc_all(struct idpf_vport *vport) + */ + static void idpf_txq_group_rel(struct idpf_vport *vport) + { ++ bool split, flow_sch_en; + int i, j; + + if (!vport->txq_grps) + return; + ++ split = idpf_is_queue_model_split(vport->txq_model); ++ flow_sch_en = !idpf_is_cap_ena(vport->adapter, IDPF_OTHER_CAPS, ++ VIRTCHNL2_CAP_SPLITQ_QSCHED); ++ + for (i = 0; i < vport->num_txq_grp; i++) { + struct idpf_txq_group *txq_grp = &vport->txq_grps[i]; + +@@ -814,8 +976,15 @@ static void idpf_txq_group_rel(struct idpf_vport *vport) + kfree(txq_grp->txqs[j]); + txq_grp->txqs[j] = NULL; + } ++ ++ if (!split) ++ continue; ++ + kfree(txq_grp->complq); + txq_grp->complq = NULL; ++ ++ if (flow_sch_en) ++ kfree(txq_grp->stashes); + } + kfree(vport->txq_grps); + vport->txq_grps = NULL; +@@ -919,7 +1088,7 @@ static int idpf_vport_init_fast_path_txqs(struct idpf_vport *vport) + { + int i, j, k = 0; + +- vport->txqs = kcalloc(vport->num_txq, sizeof(struct idpf_queue *), ++ vport->txqs = kcalloc(vport->num_txq, sizeof(*vport->txqs), + GFP_KERNEL); + + if (!vport->txqs) +@@ -1137,7 +1306,8 @@ static void idpf_vport_calc_numq_per_grp(struct idpf_vport *vport, + * @q: rx queue for which descids are set + * + */ +-static void idpf_rxq_set_descids(struct idpf_vport *vport, struct idpf_queue *q) ++static void idpf_rxq_set_descids(const struct idpf_vport *vport, ++ struct idpf_rx_queue *q) + { + if (vport->rxq_model == VIRTCHNL2_QUEUE_MODEL_SPLIT) { + q->rxdids = VIRTCHNL2_RXDID_2_FLEX_SPLITQ_M; +@@ -1158,20 +1328,22 @@ static void idpf_rxq_set_descids(struct idpf_vport *vport, struct idpf_queue *q) + */ + static int idpf_txq_group_alloc(struct idpf_vport *vport, u16 num_txq) + { +- bool flow_sch_en; +- int err, i; ++ bool split, flow_sch_en; ++ int i; + + vport->txq_grps = kcalloc(vport->num_txq_grp, + sizeof(*vport->txq_grps), GFP_KERNEL); + if (!vport->txq_grps) + return -ENOMEM; + ++ split = idpf_is_queue_model_split(vport->txq_model); + flow_sch_en = !idpf_is_cap_ena(vport->adapter, IDPF_OTHER_CAPS, + VIRTCHNL2_CAP_SPLITQ_QSCHED); + + for (i = 0; i < vport->num_txq_grp; i++) { + struct idpf_txq_group *tx_qgrp = &vport->txq_grps[i]; + struct idpf_adapter *adapter = vport->adapter; ++ struct idpf_txq_stash *stashes; + int j; + + tx_qgrp->vport = vport; +@@ -1180,45 +1352,62 @@ static int idpf_txq_group_alloc(struct idpf_vport *vport, u16 num_txq) + for (j = 0; j < tx_qgrp->num_txq; j++) { + tx_qgrp->txqs[j] = kzalloc(sizeof(*tx_qgrp->txqs[j]), + GFP_KERNEL); +- if (!tx_qgrp->txqs[j]) { +- err = -ENOMEM; ++ if (!tx_qgrp->txqs[j]) + goto err_alloc; +- } ++ } ++ ++ if (split && flow_sch_en) { ++ stashes = kcalloc(num_txq, sizeof(*stashes), ++ GFP_KERNEL); ++ if (!stashes) ++ goto err_alloc; ++ ++ tx_qgrp->stashes = stashes; + } + + for (j = 0; j < tx_qgrp->num_txq; j++) { +- struct idpf_queue *q = tx_qgrp->txqs[j]; ++ struct idpf_tx_queue *q = tx_qgrp->txqs[j]; + + q->dev = &adapter->pdev->dev; + q->desc_count = vport->txq_desc_count; + q->tx_max_bufs = idpf_get_max_tx_bufs(adapter); + q->tx_min_pkt_len = idpf_get_min_tx_pkt_len(adapter); +- q->vport = vport; ++ q->netdev = vport->netdev; + q->txq_grp = tx_qgrp; +- hash_init(q->sched_buf_hash); + +- if (flow_sch_en) +- set_bit(__IDPF_Q_FLOW_SCH_EN, q->flags); ++ if (!split) { ++ q->clean_budget = vport->compln_clean_budget; ++ idpf_queue_assign(CRC_EN, q, ++ vport->crc_enable); ++ } ++ ++ if (!flow_sch_en) ++ continue; ++ ++ if (split) { ++ q->stash = &stashes[j]; ++ hash_init(q->stash->sched_buf_hash); ++ } ++ ++ idpf_queue_set(FLOW_SCH_EN, q); + } + +- if (!idpf_is_queue_model_split(vport->txq_model)) ++ if (!split) + continue; + + tx_qgrp->complq = kcalloc(IDPF_COMPLQ_PER_GROUP, + sizeof(*tx_qgrp->complq), + GFP_KERNEL); +- if (!tx_qgrp->complq) { +- err = -ENOMEM; ++ if (!tx_qgrp->complq) + goto err_alloc; +- } + +- tx_qgrp->complq->dev = &adapter->pdev->dev; + tx_qgrp->complq->desc_count = vport->complq_desc_count; +- tx_qgrp->complq->vport = vport; + tx_qgrp->complq->txq_grp = tx_qgrp; ++ tx_qgrp->complq->netdev = vport->netdev; ++ tx_qgrp->complq->clean_budget = vport->compln_clean_budget; + + if (flow_sch_en) +- __set_bit(__IDPF_Q_FLOW_SCH_EN, tx_qgrp->complq->flags); ++ idpf_queue_set(FLOW_SCH_EN, tx_qgrp->complq); + } + + return 0; +@@ -1226,7 +1415,7 @@ static int idpf_txq_group_alloc(struct idpf_vport *vport, u16 num_txq) + err_alloc: + idpf_txq_group_rel(vport); + +- return err; ++ return -ENOMEM; + } + + /** +@@ -1238,8 +1427,6 @@ static int idpf_txq_group_alloc(struct idpf_vport *vport, u16 num_txq) + */ + static int idpf_rxq_group_alloc(struct idpf_vport *vport, u16 num_rxq) + { +- struct idpf_adapter *adapter = vport->adapter; +- struct idpf_queue *q; + int i, k, err = 0; + bool hs; + +@@ -1292,21 +1479,15 @@ static int idpf_rxq_group_alloc(struct idpf_vport *vport, u16 num_rxq) + struct idpf_bufq_set *bufq_set = + &rx_qgrp->splitq.bufq_sets[j]; + int swq_size = sizeof(struct idpf_sw_queue); ++ struct idpf_buf_queue *q; + + q = &rx_qgrp->splitq.bufq_sets[j].bufq; +- q->dev = &adapter->pdev->dev; + q->desc_count = vport->bufq_desc_count[j]; +- q->vport = vport; +- q->rxq_grp = rx_qgrp; +- q->idx = j; + q->rx_buf_size = vport->bufq_size[j]; + q->rx_buffer_low_watermark = IDPF_LOW_WATERMARK; +- q->rx_buf_stride = IDPF_RX_BUF_STRIDE; + +- if (hs) { +- q->rx_hsplit_en = true; +- q->rx_hbuf_size = IDPF_HDR_BUF_SIZE; +- } ++ idpf_queue_assign(HSPLIT_EN, q, hs); ++ q->rx_hbuf_size = hs ? IDPF_HDR_BUF_SIZE : 0; + + bufq_set->num_refillqs = num_rxq; + bufq_set->refillqs = kcalloc(num_rxq, swq_size, +@@ -1319,13 +1500,12 @@ static int idpf_rxq_group_alloc(struct idpf_vport *vport, u16 num_rxq) + struct idpf_sw_queue *refillq = + &bufq_set->refillqs[k]; + +- refillq->dev = &vport->adapter->pdev->dev; + refillq->desc_count = + vport->bufq_desc_count[j]; +- set_bit(__IDPF_Q_GEN_CHK, refillq->flags); +- set_bit(__IDPF_RFLQ_GEN_CHK, refillq->flags); ++ idpf_queue_set(GEN_CHK, refillq); ++ idpf_queue_set(RFL_GEN_CHK, refillq); + refillq->ring = kcalloc(refillq->desc_count, +- sizeof(u16), ++ sizeof(*refillq->ring), + GFP_KERNEL); + if (!refillq->ring) { + err = -ENOMEM; +@@ -1336,27 +1516,27 @@ static int idpf_rxq_group_alloc(struct idpf_vport *vport, u16 num_rxq) + + skip_splitq_rx_init: + for (j = 0; j < num_rxq; j++) { ++ struct idpf_rx_queue *q; ++ + if (!idpf_is_queue_model_split(vport->rxq_model)) { + q = rx_qgrp->singleq.rxqs[j]; + goto setup_rxq; + } + q = &rx_qgrp->splitq.rxq_sets[j]->rxq; +- rx_qgrp->splitq.rxq_sets[j]->refillq0 = ++ rx_qgrp->splitq.rxq_sets[j]->refillq[0] = + &rx_qgrp->splitq.bufq_sets[0].refillqs[j]; + if (vport->num_bufqs_per_qgrp > IDPF_SINGLE_BUFQ_PER_RXQ_GRP) +- rx_qgrp->splitq.rxq_sets[j]->refillq1 = ++ rx_qgrp->splitq.rxq_sets[j]->refillq[1] = + &rx_qgrp->splitq.bufq_sets[1].refillqs[j]; + +- if (hs) { +- q->rx_hsplit_en = true; +- q->rx_hbuf_size = IDPF_HDR_BUF_SIZE; +- } ++ idpf_queue_assign(HSPLIT_EN, q, hs); ++ q->rx_hbuf_size = hs ? IDPF_HDR_BUF_SIZE : 0; + + setup_rxq: +- q->dev = &adapter->pdev->dev; + q->desc_count = vport->rxq_desc_count; +- q->vport = vport; +- q->rxq_grp = rx_qgrp; ++ q->rx_ptype_lkup = vport->rx_ptype_lkup; ++ q->netdev = vport->netdev; ++ q->bufq_sets = rx_qgrp->splitq.bufq_sets; + q->idx = (i * num_rxq) + j; + /* In splitq mode, RXQ buffer size should be + * set to that of the first buffer queue +@@ -1445,12 +1625,13 @@ int idpf_vport_queues_alloc(struct idpf_vport *vport) + * idpf_tx_handle_sw_marker - Handle queue marker packet + * @tx_q: tx queue to handle software marker + */ +-static void idpf_tx_handle_sw_marker(struct idpf_queue *tx_q) ++static void idpf_tx_handle_sw_marker(struct idpf_tx_queue *tx_q) + { +- struct idpf_vport *vport = tx_q->vport; ++ struct idpf_netdev_priv *priv = netdev_priv(tx_q->netdev); ++ struct idpf_vport *vport = priv->vport; + int i; + +- clear_bit(__IDPF_Q_SW_MARKER, tx_q->flags); ++ idpf_queue_clear(SW_MARKER, tx_q); + /* Hardware must write marker packets to all queues associated with + * completion queues. So check if all queues received marker packets + */ +@@ -1458,7 +1639,7 @@ static void idpf_tx_handle_sw_marker(struct idpf_queue *tx_q) + /* If we're still waiting on any other TXQ marker completions, + * just return now since we cannot wake up the marker_wq yet. + */ +- if (test_bit(__IDPF_Q_SW_MARKER, vport->txqs[i]->flags)) ++ if (idpf_queue_has(SW_MARKER, vport->txqs[i])) + return; + + /* Drain complete */ +@@ -1474,7 +1655,7 @@ static void idpf_tx_handle_sw_marker(struct idpf_queue *tx_q) + * @cleaned: pointer to stats struct to track cleaned packets/bytes + * @napi_budget: Used to determine if we are in netpoll + */ +-static void idpf_tx_splitq_clean_hdr(struct idpf_queue *tx_q, ++static void idpf_tx_splitq_clean_hdr(struct idpf_tx_queue *tx_q, + struct idpf_tx_buf *tx_buf, + struct idpf_cleaned_stats *cleaned, + int napi_budget) +@@ -1505,7 +1686,8 @@ static void idpf_tx_splitq_clean_hdr(struct idpf_queue *tx_q, + * @cleaned: pointer to stats struct to track cleaned packets/bytes + * @budget: Used to determine if we are in netpoll + */ +-static void idpf_tx_clean_stashed_bufs(struct idpf_queue *txq, u16 compl_tag, ++static void idpf_tx_clean_stashed_bufs(struct idpf_tx_queue *txq, ++ u16 compl_tag, + struct idpf_cleaned_stats *cleaned, + int budget) + { +@@ -1513,7 +1695,7 @@ static void idpf_tx_clean_stashed_bufs(struct idpf_queue *txq, u16 compl_tag, + struct hlist_node *tmp_buf; + + /* Buffer completion */ +- hash_for_each_possible_safe(txq->sched_buf_hash, stash, tmp_buf, ++ hash_for_each_possible_safe(txq->stash->sched_buf_hash, stash, tmp_buf, + hlist, compl_tag) { + if (unlikely(stash->buf.compl_tag != (int)compl_tag)) + continue; +@@ -1530,7 +1712,7 @@ static void idpf_tx_clean_stashed_bufs(struct idpf_queue *txq, u16 compl_tag, + } + + /* Push shadow buf back onto stack */ +- idpf_buf_lifo_push(&txq->buf_stack, stash); ++ idpf_buf_lifo_push(&txq->stash->buf_stack, stash); + + hash_del(&stash->hlist); + } +@@ -1542,7 +1724,7 @@ static void idpf_tx_clean_stashed_bufs(struct idpf_queue *txq, u16 compl_tag, + * @txq: Tx queue to clean + * @tx_buf: buffer to store + */ +-static int idpf_stash_flow_sch_buffers(struct idpf_queue *txq, ++static int idpf_stash_flow_sch_buffers(struct idpf_tx_queue *txq, + struct idpf_tx_buf *tx_buf) + { + struct idpf_tx_stash *stash; +@@ -1551,10 +1733,10 @@ static int idpf_stash_flow_sch_buffers(struct idpf_queue *txq, + !dma_unmap_len(tx_buf, len))) + return 0; + +- stash = idpf_buf_lifo_pop(&txq->buf_stack); ++ stash = idpf_buf_lifo_pop(&txq->stash->buf_stack); + if (unlikely(!stash)) { + net_err_ratelimited("%s: No out-of-order TX buffers left!\n", +- txq->vport->netdev->name); ++ netdev_name(txq->netdev)); + + return -ENOMEM; + } +@@ -1568,7 +1750,8 @@ static int idpf_stash_flow_sch_buffers(struct idpf_queue *txq, + stash->buf.compl_tag = tx_buf->compl_tag; + + /* Add buffer to buf_hash table to be freed later */ +- hash_add(txq->sched_buf_hash, &stash->hlist, stash->buf.compl_tag); ++ hash_add(txq->stash->sched_buf_hash, &stash->hlist, ++ stash->buf.compl_tag); + + memset(tx_buf, 0, sizeof(struct idpf_tx_buf)); + +@@ -1584,7 +1767,7 @@ do { \ + if (unlikely(!(ntc))) { \ + ntc -= (txq)->desc_count; \ + buf = (txq)->tx_buf; \ +- desc = IDPF_FLEX_TX_DESC(txq, 0); \ ++ desc = &(txq)->flex_tx[0]; \ + } else { \ + (buf)++; \ + (desc)++; \ +@@ -1607,7 +1790,7 @@ do { \ + * and the buffers will be cleaned separately. The stats are not updated from + * this function when using flow-based scheduling. + */ +-static void idpf_tx_splitq_clean(struct idpf_queue *tx_q, u16 end, ++static void idpf_tx_splitq_clean(struct idpf_tx_queue *tx_q, u16 end, + int napi_budget, + struct idpf_cleaned_stats *cleaned, + bool descs_only) +@@ -1617,8 +1800,8 @@ static void idpf_tx_splitq_clean(struct idpf_queue *tx_q, u16 end, + s16 ntc = tx_q->next_to_clean; + struct idpf_tx_buf *tx_buf; + +- tx_desc = IDPF_FLEX_TX_DESC(tx_q, ntc); +- next_pending_desc = IDPF_FLEX_TX_DESC(tx_q, end); ++ tx_desc = &tx_q->flex_tx[ntc]; ++ next_pending_desc = &tx_q->flex_tx[end]; + tx_buf = &tx_q->tx_buf[ntc]; + ntc -= tx_q->desc_count; + +@@ -1703,7 +1886,7 @@ do { \ + * stashed. Returns the byte/segment count for the cleaned packet associated + * this completion tag. + */ +-static bool idpf_tx_clean_buf_ring(struct idpf_queue *txq, u16 compl_tag, ++static bool idpf_tx_clean_buf_ring(struct idpf_tx_queue *txq, u16 compl_tag, + struct idpf_cleaned_stats *cleaned, + int budget) + { +@@ -1772,14 +1955,14 @@ static bool idpf_tx_clean_buf_ring(struct idpf_queue *txq, u16 compl_tag, + * + * Returns bytes/packets cleaned + */ +-static void idpf_tx_handle_rs_completion(struct idpf_queue *txq, ++static void idpf_tx_handle_rs_completion(struct idpf_tx_queue *txq, + struct idpf_splitq_tx_compl_desc *desc, + struct idpf_cleaned_stats *cleaned, + int budget) + { + u16 compl_tag; + +- if (!test_bit(__IDPF_Q_FLOW_SCH_EN, txq->flags)) { ++ if (!idpf_queue_has(FLOW_SCH_EN, txq)) { + u16 head = le16_to_cpu(desc->q_head_compl_tag.q_head); + + return idpf_tx_splitq_clean(txq, head, budget, cleaned, false); +@@ -1802,24 +1985,23 @@ static void idpf_tx_handle_rs_completion(struct idpf_queue *txq, + * + * Returns true if there's any budget left (e.g. the clean is finished) + */ +-static bool idpf_tx_clean_complq(struct idpf_queue *complq, int budget, ++static bool idpf_tx_clean_complq(struct idpf_compl_queue *complq, int budget, + int *cleaned) + { + struct idpf_splitq_tx_compl_desc *tx_desc; +- struct idpf_vport *vport = complq->vport; + s16 ntc = complq->next_to_clean; + struct idpf_netdev_priv *np; + unsigned int complq_budget; + bool complq_ok = true; + int i; + +- complq_budget = vport->compln_clean_budget; +- tx_desc = IDPF_SPLITQ_TX_COMPLQ_DESC(complq, ntc); ++ complq_budget = complq->clean_budget; ++ tx_desc = &complq->comp[ntc]; + ntc -= complq->desc_count; + + do { + struct idpf_cleaned_stats cleaned_stats = { }; +- struct idpf_queue *tx_q; ++ struct idpf_tx_queue *tx_q; + int rel_tx_qid; + u16 hw_head; + u8 ctype; /* completion type */ +@@ -1828,7 +2010,7 @@ static bool idpf_tx_clean_complq(struct idpf_queue *complq, int budget, + /* if the descriptor isn't done, no work yet to do */ + gen = le16_get_bits(tx_desc->qid_comptype_gen, + IDPF_TXD_COMPLQ_GEN_M); +- if (test_bit(__IDPF_Q_GEN_CHK, complq->flags) != gen) ++ if (idpf_queue_has(GEN_CHK, complq) != gen) + break; + + /* Find necessary info of TX queue to clean buffers */ +@@ -1836,8 +2018,7 @@ static bool idpf_tx_clean_complq(struct idpf_queue *complq, int budget, + IDPF_TXD_COMPLQ_QID_M); + if (rel_tx_qid >= complq->txq_grp->num_txq || + !complq->txq_grp->txqs[rel_tx_qid]) { +- dev_err(&complq->vport->adapter->pdev->dev, +- "TxQ not found\n"); ++ netdev_err(complq->netdev, "TxQ not found\n"); + goto fetch_next_desc; + } + tx_q = complq->txq_grp->txqs[rel_tx_qid]; +@@ -1860,15 +2041,14 @@ static bool idpf_tx_clean_complq(struct idpf_queue *complq, int budget, + idpf_tx_handle_sw_marker(tx_q); + break; + default: +- dev_err(&tx_q->vport->adapter->pdev->dev, +- "Unknown TX completion type: %d\n", +- ctype); ++ netdev_err(tx_q->netdev, ++ "Unknown TX completion type: %d\n", ctype); + goto fetch_next_desc; + } + + u64_stats_update_begin(&tx_q->stats_sync); +- u64_stats_add(&tx_q->q_stats.tx.packets, cleaned_stats.packets); +- u64_stats_add(&tx_q->q_stats.tx.bytes, cleaned_stats.bytes); ++ u64_stats_add(&tx_q->q_stats.packets, cleaned_stats.packets); ++ u64_stats_add(&tx_q->q_stats.bytes, cleaned_stats.bytes); + tx_q->cleaned_pkts += cleaned_stats.packets; + tx_q->cleaned_bytes += cleaned_stats.bytes; + complq->num_completions++; +@@ -1879,8 +2059,8 @@ static bool idpf_tx_clean_complq(struct idpf_queue *complq, int budget, + ntc++; + if (unlikely(!ntc)) { + ntc -= complq->desc_count; +- tx_desc = IDPF_SPLITQ_TX_COMPLQ_DESC(complq, 0); +- change_bit(__IDPF_Q_GEN_CHK, complq->flags); ++ tx_desc = &complq->comp[0]; ++ idpf_queue_change(GEN_CHK, complq); + } + + prefetch(tx_desc); +@@ -1896,9 +2076,9 @@ static bool idpf_tx_clean_complq(struct idpf_queue *complq, int budget, + IDPF_TX_COMPLQ_OVERFLOW_THRESH(complq))) + complq_ok = false; + +- np = netdev_priv(complq->vport->netdev); ++ np = netdev_priv(complq->netdev); + for (i = 0; i < complq->txq_grp->num_txq; ++i) { +- struct idpf_queue *tx_q = complq->txq_grp->txqs[i]; ++ struct idpf_tx_queue *tx_q = complq->txq_grp->txqs[i]; + struct netdev_queue *nq; + bool dont_wake; + +@@ -1909,11 +2089,11 @@ static bool idpf_tx_clean_complq(struct idpf_queue *complq, int budget, + *cleaned += tx_q->cleaned_pkts; + + /* Update BQL */ +- nq = netdev_get_tx_queue(tx_q->vport->netdev, tx_q->idx); ++ nq = netdev_get_tx_queue(tx_q->netdev, tx_q->idx); + + dont_wake = !complq_ok || IDPF_TX_BUF_RSV_LOW(tx_q) || + np->state != __IDPF_VPORT_UP || +- !netif_carrier_ok(tx_q->vport->netdev); ++ !netif_carrier_ok(tx_q->netdev); + /* Check if the TXQ needs to and can be restarted */ + __netif_txq_completed_wake(nq, tx_q->cleaned_pkts, tx_q->cleaned_bytes, + IDPF_DESC_UNUSED(tx_q), IDPF_TX_WAKE_THRESH, +@@ -1969,29 +2149,6 @@ void idpf_tx_splitq_build_flow_desc(union idpf_tx_flex_desc *desc, + desc->flow.qw1.compl_tag = cpu_to_le16(params->compl_tag); + } + +-/** +- * idpf_tx_maybe_stop_common - 1st level check for common Tx stop conditions +- * @tx_q: the queue to be checked +- * @size: number of descriptors we want to assure is available +- * +- * Returns 0 if stop is not needed +- */ +-int idpf_tx_maybe_stop_common(struct idpf_queue *tx_q, unsigned int size) +-{ +- struct netdev_queue *nq; +- +- if (likely(IDPF_DESC_UNUSED(tx_q) >= size)) +- return 0; +- +- u64_stats_update_begin(&tx_q->stats_sync); +- u64_stats_inc(&tx_q->q_stats.tx.q_busy); +- u64_stats_update_end(&tx_q->stats_sync); +- +- nq = netdev_get_tx_queue(tx_q->vport->netdev, tx_q->idx); +- +- return netif_txq_maybe_stop(nq, IDPF_DESC_UNUSED(tx_q), size, size); +-} +- + /** + * idpf_tx_maybe_stop_splitq - 1st level check for Tx splitq stop conditions + * @tx_q: the queue to be checked +@@ -1999,11 +2156,11 @@ int idpf_tx_maybe_stop_common(struct idpf_queue *tx_q, unsigned int size) + * + * Returns 0 if stop is not needed + */ +-static int idpf_tx_maybe_stop_splitq(struct idpf_queue *tx_q, ++static int idpf_tx_maybe_stop_splitq(struct idpf_tx_queue *tx_q, + unsigned int descs_needed) + { + if (idpf_tx_maybe_stop_common(tx_q, descs_needed)) +- goto splitq_stop; ++ goto out; + + /* If there are too many outstanding completions expected on the + * completion queue, stop the TX queue to give the device some time to +@@ -2022,10 +2179,12 @@ static int idpf_tx_maybe_stop_splitq(struct idpf_queue *tx_q, + return 0; + + splitq_stop: ++ netif_stop_subqueue(tx_q->netdev, tx_q->idx); ++ ++out: + u64_stats_update_begin(&tx_q->stats_sync); +- u64_stats_inc(&tx_q->q_stats.tx.q_busy); ++ u64_stats_inc(&tx_q->q_stats.q_busy); + u64_stats_update_end(&tx_q->stats_sync); +- netif_stop_subqueue(tx_q->vport->netdev, tx_q->idx); + + return -EBUSY; + } +@@ -2040,15 +2199,19 @@ static int idpf_tx_maybe_stop_splitq(struct idpf_queue *tx_q, + * to do a register write to update our queue status. We know this can only + * mean tail here as HW should be owning head for TX. + */ +-void idpf_tx_buf_hw_update(struct idpf_queue *tx_q, u32 val, ++void idpf_tx_buf_hw_update(struct idpf_tx_queue *tx_q, u32 val, + bool xmit_more) + { + struct netdev_queue *nq; + +- nq = netdev_get_tx_queue(tx_q->vport->netdev, tx_q->idx); ++ nq = netdev_get_tx_queue(tx_q->netdev, tx_q->idx); + tx_q->next_to_use = val; + +- idpf_tx_maybe_stop_common(tx_q, IDPF_TX_DESC_NEEDED); ++ if (idpf_tx_maybe_stop_common(tx_q, IDPF_TX_DESC_NEEDED)) { ++ u64_stats_update_begin(&tx_q->stats_sync); ++ u64_stats_inc(&tx_q->q_stats.q_busy); ++ u64_stats_update_end(&tx_q->stats_sync); ++ } + + /* Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only +@@ -2069,7 +2232,7 @@ void idpf_tx_buf_hw_update(struct idpf_queue *tx_q, u32 val, + * + * Returns number of data descriptors needed for this skb. + */ +-unsigned int idpf_tx_desc_count_required(struct idpf_queue *txq, ++unsigned int idpf_tx_desc_count_required(struct idpf_tx_queue *txq, + struct sk_buff *skb) + { + const struct skb_shared_info *shinfo; +@@ -2102,7 +2265,7 @@ unsigned int idpf_tx_desc_count_required(struct idpf_queue *txq, + + count = idpf_size_to_txd_count(skb->len); + u64_stats_update_begin(&txq->stats_sync); +- u64_stats_inc(&txq->q_stats.tx.linearize); ++ u64_stats_inc(&txq->q_stats.linearize); + u64_stats_update_end(&txq->stats_sync); + } + +@@ -2116,11 +2279,11 @@ unsigned int idpf_tx_desc_count_required(struct idpf_queue *txq, + * @first: original first buffer info buffer for packet + * @idx: starting point on ring to unwind + */ +-void idpf_tx_dma_map_error(struct idpf_queue *txq, struct sk_buff *skb, ++void idpf_tx_dma_map_error(struct idpf_tx_queue *txq, struct sk_buff *skb, + struct idpf_tx_buf *first, u16 idx) + { + u64_stats_update_begin(&txq->stats_sync); +- u64_stats_inc(&txq->q_stats.tx.dma_map_errs); ++ u64_stats_inc(&txq->q_stats.dma_map_errs); + u64_stats_update_end(&txq->stats_sync); + + /* clear dma mappings for failed tx_buf map */ +@@ -2143,7 +2306,7 @@ void idpf_tx_dma_map_error(struct idpf_queue *txq, struct sk_buff *skb, + * used one additional descriptor for a context + * descriptor. Reset that here. + */ +- tx_desc = IDPF_FLEX_TX_DESC(txq, idx); ++ tx_desc = &txq->flex_tx[idx]; + memset(tx_desc, 0, sizeof(struct idpf_flex_tx_ctx_desc)); + if (idx == 0) + idx = txq->desc_count; +@@ -2159,7 +2322,7 @@ void idpf_tx_dma_map_error(struct idpf_queue *txq, struct sk_buff *skb, + * @txq: the tx ring to wrap + * @ntu: ring index to bump + */ +-static unsigned int idpf_tx_splitq_bump_ntu(struct idpf_queue *txq, u16 ntu) ++static unsigned int idpf_tx_splitq_bump_ntu(struct idpf_tx_queue *txq, u16 ntu) + { + ntu++; + +@@ -2181,7 +2344,7 @@ static unsigned int idpf_tx_splitq_bump_ntu(struct idpf_queue *txq, u16 ntu) + * and gets a physical address for each memory location and programs + * it and the length into the transmit flex descriptor. + */ +-static void idpf_tx_splitq_map(struct idpf_queue *tx_q, ++static void idpf_tx_splitq_map(struct idpf_tx_queue *tx_q, + struct idpf_tx_splitq_params *params, + struct idpf_tx_buf *first) + { +@@ -2202,7 +2365,7 @@ static void idpf_tx_splitq_map(struct idpf_queue *tx_q, + data_len = skb->data_len; + size = skb_headlen(skb); + +- tx_desc = IDPF_FLEX_TX_DESC(tx_q, i); ++ tx_desc = &tx_q->flex_tx[i]; + + dma = dma_map_single(tx_q->dev, skb->data, size, DMA_TO_DEVICE); + +@@ -2275,7 +2438,7 @@ static void idpf_tx_splitq_map(struct idpf_queue *tx_q, + i++; + + if (i == tx_q->desc_count) { +- tx_desc = IDPF_FLEX_TX_DESC(tx_q, 0); ++ tx_desc = &tx_q->flex_tx[0]; + i = 0; + tx_q->compl_tag_cur_gen = + IDPF_TX_ADJ_COMPL_TAG_GEN(tx_q); +@@ -2320,7 +2483,7 @@ static void idpf_tx_splitq_map(struct idpf_queue *tx_q, + i++; + + if (i == tx_q->desc_count) { +- tx_desc = IDPF_FLEX_TX_DESC(tx_q, 0); ++ tx_desc = &tx_q->flex_tx[0]; + i = 0; + tx_q->compl_tag_cur_gen = IDPF_TX_ADJ_COMPL_TAG_GEN(tx_q); + } +@@ -2348,7 +2511,7 @@ static void idpf_tx_splitq_map(struct idpf_queue *tx_q, + tx_q->txq_grp->num_completions_pending++; + + /* record bytecount for BQL */ +- nq = netdev_get_tx_queue(tx_q->vport->netdev, tx_q->idx); ++ nq = netdev_get_tx_queue(tx_q->netdev, tx_q->idx); + netdev_tx_sent_queue(nq, first->bytecount); + + idpf_tx_buf_hw_update(tx_q, i, netdev_xmit_more()); +@@ -2525,8 +2688,8 @@ static bool __idpf_chk_linearize(struct sk_buff *skb, unsigned int max_bufs) + * E.g.: a packet with 7 fragments can require 9 DMA transactions; 1 for TSO + * header, 1 for segment payload, and then 7 for the fragments. + */ +-bool idpf_chk_linearize(struct sk_buff *skb, unsigned int max_bufs, +- unsigned int count) ++static bool idpf_chk_linearize(struct sk_buff *skb, unsigned int max_bufs, ++ unsigned int count) + { + if (likely(count < max_bufs)) + return false; +@@ -2544,7 +2707,7 @@ bool idpf_chk_linearize(struct sk_buff *skb, unsigned int max_bufs, + * ring entry to reflect that this index is a context descriptor + */ + static struct idpf_flex_tx_ctx_desc * +-idpf_tx_splitq_get_ctx_desc(struct idpf_queue *txq) ++idpf_tx_splitq_get_ctx_desc(struct idpf_tx_queue *txq) + { + struct idpf_flex_tx_ctx_desc *desc; + int i = txq->next_to_use; +@@ -2553,7 +2716,7 @@ idpf_tx_splitq_get_ctx_desc(struct idpf_queue *txq) + txq->tx_buf[i].compl_tag = IDPF_SPLITQ_TX_INVAL_COMPL_TAG; + + /* grab the next descriptor */ +- desc = IDPF_FLEX_TX_CTX_DESC(txq, i); ++ desc = &txq->flex_ctx[i]; + txq->next_to_use = idpf_tx_splitq_bump_ntu(txq, i); + + return desc; +@@ -2564,10 +2727,10 @@ idpf_tx_splitq_get_ctx_desc(struct idpf_queue *txq) + * @tx_q: queue to send buffer on + * @skb: pointer to skb + */ +-netdev_tx_t idpf_tx_drop_skb(struct idpf_queue *tx_q, struct sk_buff *skb) ++netdev_tx_t idpf_tx_drop_skb(struct idpf_tx_queue *tx_q, struct sk_buff *skb) + { + u64_stats_update_begin(&tx_q->stats_sync); +- u64_stats_inc(&tx_q->q_stats.tx.skb_drops); ++ u64_stats_inc(&tx_q->q_stats.skb_drops); + u64_stats_update_end(&tx_q->stats_sync); + + idpf_tx_buf_hw_update(tx_q, tx_q->next_to_use, false); +@@ -2585,7 +2748,7 @@ netdev_tx_t idpf_tx_drop_skb(struct idpf_queue *tx_q, struct sk_buff *skb) + * Returns NETDEV_TX_OK if sent, else an error code + */ + static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb, +- struct idpf_queue *tx_q) ++ struct idpf_tx_queue *tx_q) + { + struct idpf_tx_splitq_params tx_params = { }; + struct idpf_tx_buf *first; +@@ -2625,7 +2788,7 @@ static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb, + ctx_desc->tso.qw0.hdr_len = tx_params.offload.tso_hdr_len; + + u64_stats_update_begin(&tx_q->stats_sync); +- u64_stats_inc(&tx_q->q_stats.tx.lso_pkts); ++ u64_stats_inc(&tx_q->q_stats.lso_pkts); + u64_stats_update_end(&tx_q->stats_sync); + } + +@@ -2642,7 +2805,7 @@ static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb, + first->bytecount = max_t(unsigned int, skb->len, ETH_ZLEN); + } + +- if (test_bit(__IDPF_Q_FLOW_SCH_EN, tx_q->flags)) { ++ if (idpf_queue_has(FLOW_SCH_EN, tx_q)) { + tx_params.dtype = IDPF_TX_DESC_DTYPE_FLEX_FLOW_SCHE; + tx_params.eop_cmd = IDPF_TXD_FLEX_FLOW_CMD_EOP; + /* Set the RE bit to catch any packets that may have not been +@@ -2672,17 +2835,16 @@ static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb, + } + + /** +- * idpf_tx_splitq_start - Selects the right Tx queue to send buffer ++ * idpf_tx_start - Selects the right Tx queue to send buffer + * @skb: send buffer + * @netdev: network interface device structure + * + * Returns NETDEV_TX_OK if sent, else an error code + */ +-netdev_tx_t idpf_tx_splitq_start(struct sk_buff *skb, +- struct net_device *netdev) ++netdev_tx_t idpf_tx_start(struct sk_buff *skb, struct net_device *netdev) + { + struct idpf_vport *vport = idpf_netdev_to_vport(netdev); +- struct idpf_queue *tx_q; ++ struct idpf_tx_queue *tx_q; + + if (unlikely(skb_get_queue_mapping(skb) >= vport->num_txq)) { + dev_kfree_skb_any(skb); +@@ -2701,7 +2863,10 @@ netdev_tx_t idpf_tx_splitq_start(struct sk_buff *skb, + return NETDEV_TX_OK; + } + +- return idpf_tx_splitq_frame(skb, tx_q); ++ if (idpf_is_queue_model_split(vport->txq_model)) ++ return idpf_tx_splitq_frame(skb, tx_q); ++ else ++ return idpf_tx_singleq_frame(skb, tx_q); + } + + /** +@@ -2735,13 +2900,14 @@ enum pkt_hash_types idpf_ptype_to_htype(const struct idpf_rx_ptype_decoded *deco + * @rx_desc: Receive descriptor + * @decoded: Decoded Rx packet type related fields + */ +-static void idpf_rx_hash(struct idpf_queue *rxq, struct sk_buff *skb, +- struct virtchnl2_rx_flex_desc_adv_nic_3 *rx_desc, +- struct idpf_rx_ptype_decoded *decoded) ++static void ++idpf_rx_hash(const struct idpf_rx_queue *rxq, struct sk_buff *skb, ++ const struct virtchnl2_rx_flex_desc_adv_nic_3 *rx_desc, ++ struct idpf_rx_ptype_decoded *decoded) + { + u32 hash; + +- if (unlikely(!idpf_is_feature_ena(rxq->vport, NETIF_F_RXHASH))) ++ if (unlikely(!(rxq->netdev->features & NETIF_F_RXHASH))) + return; + + hash = le16_to_cpu(rx_desc->hash1) | +@@ -2760,14 +2926,14 @@ static void idpf_rx_hash(struct idpf_queue *rxq, struct sk_buff *skb, + * + * skb->protocol must be set before this function is called + */ +-static void idpf_rx_csum(struct idpf_queue *rxq, struct sk_buff *skb, ++static void idpf_rx_csum(struct idpf_rx_queue *rxq, struct sk_buff *skb, + struct idpf_rx_csum_decoded *csum_bits, + struct idpf_rx_ptype_decoded *decoded) + { + bool ipv4, ipv6; + + /* check if Rx checksum is enabled */ +- if (unlikely(!idpf_is_feature_ena(rxq->vport, NETIF_F_RXCSUM))) ++ if (unlikely(!(rxq->netdev->features & NETIF_F_RXCSUM))) + return; + + /* check if HW has decoded the packet and checksum */ +@@ -2814,7 +2980,7 @@ static void idpf_rx_csum(struct idpf_queue *rxq, struct sk_buff *skb, + + checksum_fail: + u64_stats_update_begin(&rxq->stats_sync); +- u64_stats_inc(&rxq->q_stats.rx.hw_csum_err); ++ u64_stats_inc(&rxq->q_stats.hw_csum_err); + u64_stats_update_end(&rxq->stats_sync); + } + +@@ -2824,8 +2990,9 @@ static void idpf_rx_csum(struct idpf_queue *rxq, struct sk_buff *skb, + * @csum: structure to extract checksum fields + * + **/ +-static void idpf_rx_splitq_extract_csum_bits(struct virtchnl2_rx_flex_desc_adv_nic_3 *rx_desc, +- struct idpf_rx_csum_decoded *csum) ++static void ++idpf_rx_splitq_extract_csum_bits(const struct virtchnl2_rx_flex_desc_adv_nic_3 *rx_desc, ++ struct idpf_rx_csum_decoded *csum) + { + u8 qword0, qword1; + +@@ -2860,8 +3027,8 @@ static void idpf_rx_splitq_extract_csum_bits(struct virtchnl2_rx_flex_desc_adv_n + * Populate the skb fields with the total number of RSC segments, RSC payload + * length and packet type. + */ +-static int idpf_rx_rsc(struct idpf_queue *rxq, struct sk_buff *skb, +- struct virtchnl2_rx_flex_desc_adv_nic_3 *rx_desc, ++static int idpf_rx_rsc(struct idpf_rx_queue *rxq, struct sk_buff *skb, ++ const struct virtchnl2_rx_flex_desc_adv_nic_3 *rx_desc, + struct idpf_rx_ptype_decoded *decoded) + { + u16 rsc_segments, rsc_seg_len; +@@ -2914,7 +3081,7 @@ static int idpf_rx_rsc(struct idpf_queue *rxq, struct sk_buff *skb, + tcp_gro_complete(skb); + + u64_stats_update_begin(&rxq->stats_sync); +- u64_stats_inc(&rxq->q_stats.rx.rsc_pkts); ++ u64_stats_inc(&rxq->q_stats.rsc_pkts); + u64_stats_update_end(&rxq->stats_sync); + + return 0; +@@ -2930,9 +3097,9 @@ static int idpf_rx_rsc(struct idpf_queue *rxq, struct sk_buff *skb, + * order to populate the hash, checksum, protocol, and + * other fields within the skb. + */ +-static int idpf_rx_process_skb_fields(struct idpf_queue *rxq, +- struct sk_buff *skb, +- struct virtchnl2_rx_flex_desc_adv_nic_3 *rx_desc) ++static int ++idpf_rx_process_skb_fields(struct idpf_rx_queue *rxq, struct sk_buff *skb, ++ const struct virtchnl2_rx_flex_desc_adv_nic_3 *rx_desc) + { + struct idpf_rx_csum_decoded csum_bits = { }; + struct idpf_rx_ptype_decoded decoded; +@@ -2940,19 +3107,13 @@ static int idpf_rx_process_skb_fields(struct idpf_queue *rxq, + + rx_ptype = le16_get_bits(rx_desc->ptype_err_fflags0, + VIRTCHNL2_RX_FLEX_DESC_ADV_PTYPE_M); +- +- skb->protocol = eth_type_trans(skb, rxq->vport->netdev); +- +- decoded = rxq->vport->rx_ptype_lkup[rx_ptype]; +- /* If we don't know the ptype we can't do anything else with it. Just +- * pass it up the stack as-is. +- */ +- if (!decoded.known) +- return 0; ++ decoded = rxq->rx_ptype_lkup[rx_ptype]; + + /* process RSS/hash */ + idpf_rx_hash(rxq, skb, rx_desc, &decoded); + ++ skb->protocol = eth_type_trans(skb, rxq->netdev); ++ + if (le16_get_bits(rx_desc->hdrlen_flags, + VIRTCHNL2_RX_FLEX_DESC_ADV_RSC_M)) + return idpf_rx_rsc(rxq, skb, rx_desc, &decoded); +@@ -2992,7 +3153,7 @@ void idpf_rx_add_frag(struct idpf_rx_buf *rx_buf, struct sk_buff *skb, + * data from the current receive descriptor, taking care to set up the + * skb correctly. + */ +-struct sk_buff *idpf_rx_construct_skb(struct idpf_queue *rxq, ++struct sk_buff *idpf_rx_construct_skb(const struct idpf_rx_queue *rxq, + struct idpf_rx_buf *rx_buf, + unsigned int size) + { +@@ -3005,7 +3166,7 @@ struct sk_buff *idpf_rx_construct_skb(struct idpf_queue *rxq, + /* prefetch first cache line of first page */ + net_prefetch(va); + /* allocate a skb to store the frags */ +- skb = napi_alloc_skb(&rxq->q_vector->napi, IDPF_RX_HDR_SIZE); ++ skb = napi_alloc_skb(rxq->napi, IDPF_RX_HDR_SIZE); + if (unlikely(!skb)) { + idpf_rx_put_page(rx_buf); + +@@ -3052,14 +3213,14 @@ struct sk_buff *idpf_rx_construct_skb(struct idpf_queue *rxq, + * the current receive descriptor, taking care to set up the skb correctly. + * This specifically uses a header buffer to start building the skb. + */ +-static struct sk_buff *idpf_rx_hdr_construct_skb(struct idpf_queue *rxq, +- const void *va, +- unsigned int size) ++static struct sk_buff * ++idpf_rx_hdr_construct_skb(const struct idpf_rx_queue *rxq, const void *va, ++ unsigned int size) + { + struct sk_buff *skb; + + /* allocate a skb to store the frags */ +- skb = napi_alloc_skb(&rxq->q_vector->napi, size); ++ skb = napi_alloc_skb(rxq->napi, size); + if (unlikely(!skb)) + return NULL; + +@@ -3115,10 +3276,10 @@ static bool idpf_rx_splitq_is_eop(struct virtchnl2_rx_flex_desc_adv_nic_3 *rx_de + * + * Returns amount of work completed + */ +-static int idpf_rx_splitq_clean(struct idpf_queue *rxq, int budget) ++static int idpf_rx_splitq_clean(struct idpf_rx_queue *rxq, int budget) + { + int total_rx_bytes = 0, total_rx_pkts = 0; +- struct idpf_queue *rx_bufq = NULL; ++ struct idpf_buf_queue *rx_bufq = NULL; + struct sk_buff *skb = rxq->skb; + u16 ntc = rxq->next_to_clean; + +@@ -3128,7 +3289,6 @@ static int idpf_rx_splitq_clean(struct idpf_queue *rxq, int budget) + struct idpf_sw_queue *refillq = NULL; + struct idpf_rxq_set *rxq_set = NULL; + struct idpf_rx_buf *rx_buf = NULL; +- union virtchnl2_rx_desc *desc; + unsigned int pkt_len = 0; + unsigned int hdr_len = 0; + u16 gen_id, buf_id = 0; +@@ -3138,8 +3298,7 @@ static int idpf_rx_splitq_clean(struct idpf_queue *rxq, int budget) + u8 rxdid; + + /* get the Rx desc from Rx queue based on 'next_to_clean' */ +- desc = IDPF_RX_DESC(rxq, ntc); +- rx_desc = (struct virtchnl2_rx_flex_desc_adv_nic_3 *)desc; ++ rx_desc = &rxq->rx[ntc].flex_adv_nic_3_wb; + + /* This memory barrier is needed to keep us from reading + * any other fields out of the rx_desc +@@ -3150,7 +3309,7 @@ static int idpf_rx_splitq_clean(struct idpf_queue *rxq, int budget) + gen_id = le16_get_bits(rx_desc->pktlen_gen_bufq_id, + VIRTCHNL2_RX_FLEX_DESC_ADV_GEN_M); + +- if (test_bit(__IDPF_Q_GEN_CHK, rxq->flags) != gen_id) ++ if (idpf_queue_has(GEN_CHK, rxq) != gen_id) + break; + + rxdid = FIELD_GET(VIRTCHNL2_RX_FLEX_DESC_ADV_RXDID_M, +@@ -3158,7 +3317,7 @@ static int idpf_rx_splitq_clean(struct idpf_queue *rxq, int budget) + if (rxdid != VIRTCHNL2_RXDID_2_FLEX_SPLITQ) { + IDPF_RX_BUMP_NTC(rxq, ntc); + u64_stats_update_begin(&rxq->stats_sync); +- u64_stats_inc(&rxq->q_stats.rx.bad_descs); ++ u64_stats_inc(&rxq->q_stats.bad_descs); + u64_stats_update_end(&rxq->stats_sync); + continue; + } +@@ -3176,7 +3335,7 @@ static int idpf_rx_splitq_clean(struct idpf_queue *rxq, int budget) + * data/payload buffer. + */ + u64_stats_update_begin(&rxq->stats_sync); +- u64_stats_inc(&rxq->q_stats.rx.hsplit_buf_ovf); ++ u64_stats_inc(&rxq->q_stats.hsplit_buf_ovf); + u64_stats_update_end(&rxq->stats_sync); + goto bypass_hsplit; + } +@@ -3189,13 +3348,10 @@ static int idpf_rx_splitq_clean(struct idpf_queue *rxq, int budget) + VIRTCHNL2_RX_FLEX_DESC_ADV_BUFQ_ID_M); + + rxq_set = container_of(rxq, struct idpf_rxq_set, rxq); +- if (!bufq_id) +- refillq = rxq_set->refillq0; +- else +- refillq = rxq_set->refillq1; ++ refillq = rxq_set->refillq[bufq_id]; + + /* retrieve buffer from the rxq */ +- rx_bufq = &rxq->rxq_grp->splitq.bufq_sets[bufq_id].bufq; ++ rx_bufq = &rxq->bufq_sets[bufq_id].bufq; + + buf_id = le16_to_cpu(rx_desc->buf_id); + +@@ -3207,7 +3363,7 @@ static int idpf_rx_splitq_clean(struct idpf_queue *rxq, int budget) + + skb = idpf_rx_hdr_construct_skb(rxq, va, hdr_len); + u64_stats_update_begin(&rxq->stats_sync); +- u64_stats_inc(&rxq->q_stats.rx.hsplit_pkts); ++ u64_stats_inc(&rxq->q_stats.hsplit_pkts); + u64_stats_update_end(&rxq->stats_sync); + } + +@@ -3250,7 +3406,7 @@ static int idpf_rx_splitq_clean(struct idpf_queue *rxq, int budget) + } + + /* send completed skb up the stack */ +- napi_gro_receive(&rxq->q_vector->napi, skb); ++ napi_gro_receive(rxq->napi, skb); + skb = NULL; + + /* update budget accounting */ +@@ -3261,8 +3417,8 @@ static int idpf_rx_splitq_clean(struct idpf_queue *rxq, int budget) + + rxq->skb = skb; + u64_stats_update_begin(&rxq->stats_sync); +- u64_stats_add(&rxq->q_stats.rx.packets, total_rx_pkts); +- u64_stats_add(&rxq->q_stats.rx.bytes, total_rx_bytes); ++ u64_stats_add(&rxq->q_stats.packets, total_rx_pkts); ++ u64_stats_add(&rxq->q_stats.bytes, total_rx_bytes); + u64_stats_update_end(&rxq->stats_sync); + + /* guarantee a trip back through this routine if there was a failure */ +@@ -3272,19 +3428,16 @@ static int idpf_rx_splitq_clean(struct idpf_queue *rxq, int budget) + /** + * idpf_rx_update_bufq_desc - Update buffer queue descriptor + * @bufq: Pointer to the buffer queue +- * @refill_desc: SW Refill queue descriptor containing buffer ID ++ * @buf_id: buffer ID + * @buf_desc: Buffer queue descriptor + * + * Return 0 on success and negative on failure. + */ +-static int idpf_rx_update_bufq_desc(struct idpf_queue *bufq, u16 refill_desc, ++static int idpf_rx_update_bufq_desc(struct idpf_buf_queue *bufq, u32 buf_id, + struct virtchnl2_splitq_rx_buf_desc *buf_desc) + { + struct idpf_rx_buf *buf; + dma_addr_t addr; +- u16 buf_id; +- +- buf_id = FIELD_GET(IDPF_RX_BI_BUFID_M, refill_desc); + + buf = &bufq->rx_buf.buf[buf_id]; + +@@ -3295,7 +3448,7 @@ static int idpf_rx_update_bufq_desc(struct idpf_queue *bufq, u16 refill_desc, + buf_desc->pkt_addr = cpu_to_le64(addr); + buf_desc->qword0.buf_id = cpu_to_le16(buf_id); + +- if (!bufq->rx_hsplit_en) ++ if (!idpf_queue_has(HSPLIT_EN, bufq)) + return 0; + + buf_desc->hdr_addr = cpu_to_le64(bufq->rx_buf.hdr_buf_pa + +@@ -3311,38 +3464,37 @@ static int idpf_rx_update_bufq_desc(struct idpf_queue *bufq, u16 refill_desc, + * + * This function takes care of the buffer refill management + */ +-static void idpf_rx_clean_refillq(struct idpf_queue *bufq, ++static void idpf_rx_clean_refillq(struct idpf_buf_queue *bufq, + struct idpf_sw_queue *refillq) + { + struct virtchnl2_splitq_rx_buf_desc *buf_desc; + u16 bufq_nta = bufq->next_to_alloc; + u16 ntc = refillq->next_to_clean; + int cleaned = 0; +- u16 gen; + +- buf_desc = IDPF_SPLITQ_RX_BUF_DESC(bufq, bufq_nta); ++ buf_desc = &bufq->split_buf[bufq_nta]; + + /* make sure we stop at ring wrap in the unlikely case ring is full */ + while (likely(cleaned < refillq->desc_count)) { +- u16 refill_desc = IDPF_SPLITQ_RX_BI_DESC(refillq, ntc); ++ u32 buf_id, refill_desc = refillq->ring[ntc]; + bool failure; + +- gen = FIELD_GET(IDPF_RX_BI_GEN_M, refill_desc); +- if (test_bit(__IDPF_RFLQ_GEN_CHK, refillq->flags) != gen) ++ if (idpf_queue_has(RFL_GEN_CHK, refillq) != ++ !!(refill_desc & IDPF_RX_BI_GEN_M)) + break; + +- failure = idpf_rx_update_bufq_desc(bufq, refill_desc, +- buf_desc); ++ buf_id = FIELD_GET(IDPF_RX_BI_BUFID_M, refill_desc); ++ failure = idpf_rx_update_bufq_desc(bufq, buf_id, buf_desc); + if (failure) + break; + + if (unlikely(++ntc == refillq->desc_count)) { +- change_bit(__IDPF_RFLQ_GEN_CHK, refillq->flags); ++ idpf_queue_change(RFL_GEN_CHK, refillq); + ntc = 0; + } + + if (unlikely(++bufq_nta == bufq->desc_count)) { +- buf_desc = IDPF_SPLITQ_RX_BUF_DESC(bufq, 0); ++ buf_desc = &bufq->split_buf[0]; + bufq_nta = 0; + } else { + buf_desc++; +@@ -3376,7 +3528,7 @@ static void idpf_rx_clean_refillq(struct idpf_queue *bufq, + * this vector. Returns true if clean is complete within budget, false + * otherwise. + */ +-static void idpf_rx_clean_refillq_all(struct idpf_queue *bufq) ++static void idpf_rx_clean_refillq_all(struct idpf_buf_queue *bufq) + { + struct idpf_bufq_set *bufq_set; + int i; +@@ -3439,6 +3591,8 @@ void idpf_vport_intr_rel(struct idpf_vport *vport) + for (u32 v_idx = 0; v_idx < vport->num_q_vectors; v_idx++) { + struct idpf_q_vector *q_vector = &vport->q_vectors[v_idx]; + ++ kfree(q_vector->complq); ++ q_vector->complq = NULL; + kfree(q_vector->bufq); + q_vector->bufq = NULL; + kfree(q_vector->tx); +@@ -3557,13 +3711,13 @@ static void idpf_net_dim(struct idpf_q_vector *q_vector) + goto check_rx_itr; + + for (i = 0, packets = 0, bytes = 0; i < q_vector->num_txq; i++) { +- struct idpf_queue *txq = q_vector->tx[i]; ++ struct idpf_tx_queue *txq = q_vector->tx[i]; + unsigned int start; + + do { + start = u64_stats_fetch_begin(&txq->stats_sync); +- packets += u64_stats_read(&txq->q_stats.tx.packets); +- bytes += u64_stats_read(&txq->q_stats.tx.bytes); ++ packets += u64_stats_read(&txq->q_stats.packets); ++ bytes += u64_stats_read(&txq->q_stats.bytes); + } while (u64_stats_fetch_retry(&txq->stats_sync, start)); + } + +@@ -3576,13 +3730,13 @@ static void idpf_net_dim(struct idpf_q_vector *q_vector) + return; + + for (i = 0, packets = 0, bytes = 0; i < q_vector->num_rxq; i++) { +- struct idpf_queue *rxq = q_vector->rx[i]; ++ struct idpf_rx_queue *rxq = q_vector->rx[i]; + unsigned int start; + + do { + start = u64_stats_fetch_begin(&rxq->stats_sync); +- packets += u64_stats_read(&rxq->q_stats.rx.packets); +- bytes += u64_stats_read(&rxq->q_stats.rx.bytes); ++ packets += u64_stats_read(&rxq->q_stats.packets); ++ bytes += u64_stats_read(&rxq->q_stats.bytes); + } while (u64_stats_fetch_retry(&rxq->stats_sync, start)); + } + +@@ -3826,16 +3980,17 @@ static void idpf_vport_intr_napi_ena_all(struct idpf_vport *vport) + static bool idpf_tx_splitq_clean_all(struct idpf_q_vector *q_vec, + int budget, int *cleaned) + { +- u16 num_txq = q_vec->num_txq; ++ u16 num_complq = q_vec->num_complq; + bool clean_complete = true; + int i, budget_per_q; + +- if (unlikely(!num_txq)) ++ if (unlikely(!num_complq)) + return true; + +- budget_per_q = DIV_ROUND_UP(budget, num_txq); +- for (i = 0; i < num_txq; i++) +- clean_complete &= idpf_tx_clean_complq(q_vec->tx[i], ++ budget_per_q = DIV_ROUND_UP(budget, num_complq); ++ ++ for (i = 0; i < num_complq; i++) ++ clean_complete &= idpf_tx_clean_complq(q_vec->complq[i], + budget_per_q, cleaned); + + return clean_complete; +@@ -3862,7 +4017,7 @@ static bool idpf_rx_splitq_clean_all(struct idpf_q_vector *q_vec, int budget, + */ + budget_per_q = num_rxq ? max(budget / num_rxq, 1) : 0; + for (i = 0; i < num_rxq; i++) { +- struct idpf_queue *rxq = q_vec->rx[i]; ++ struct idpf_rx_queue *rxq = q_vec->rx[i]; + int pkts_cleaned_per_q; + + pkts_cleaned_per_q = idpf_rx_splitq_clean(rxq, budget_per_q); +@@ -3917,8 +4072,8 @@ static int idpf_vport_splitq_napi_poll(struct napi_struct *napi, int budget) + * queues virtchnl message, as the interrupts will be disabled after + * that + */ +- if (unlikely(q_vector->num_txq && test_bit(__IDPF_Q_POLL_MODE, +- q_vector->tx[0]->flags))) ++ if (unlikely(q_vector->num_txq && idpf_queue_has(POLL_MODE, ++ q_vector->tx[0]))) + return budget; + else + return work_done; +@@ -3932,27 +4087,28 @@ static int idpf_vport_splitq_napi_poll(struct napi_struct *napi, int budget) + */ + static void idpf_vport_intr_map_vector_to_qs(struct idpf_vport *vport) + { ++ bool split = idpf_is_queue_model_split(vport->rxq_model); + u16 num_txq_grp = vport->num_txq_grp; +- int i, j, qv_idx, bufq_vidx = 0; + struct idpf_rxq_group *rx_qgrp; + struct idpf_txq_group *tx_qgrp; +- struct idpf_queue *q, *bufq; +- u16 q_index; ++ u32 i, qv_idx, q_index; + + for (i = 0, qv_idx = 0; i < vport->num_rxq_grp; i++) { + u16 num_rxq; + ++ if (qv_idx >= vport->num_q_vectors) ++ qv_idx = 0; ++ + rx_qgrp = &vport->rxq_grps[i]; +- if (idpf_is_queue_model_split(vport->rxq_model)) ++ if (split) + num_rxq = rx_qgrp->splitq.num_rxq_sets; + else + num_rxq = rx_qgrp->singleq.num_rxq; + +- for (j = 0; j < num_rxq; j++) { +- if (qv_idx >= vport->num_q_vectors) +- qv_idx = 0; ++ for (u32 j = 0; j < num_rxq; j++) { ++ struct idpf_rx_queue *q; + +- if (idpf_is_queue_model_split(vport->rxq_model)) ++ if (split) + q = &rx_qgrp->splitq.rxq_sets[j]->rxq; + else + q = rx_qgrp->singleq.rxqs[j]; +@@ -3960,52 +4116,53 @@ static void idpf_vport_intr_map_vector_to_qs(struct idpf_vport *vport) + q_index = q->q_vector->num_rxq; + q->q_vector->rx[q_index] = q; + q->q_vector->num_rxq++; +- qv_idx++; ++ ++ if (split) ++ q->napi = &q->q_vector->napi; + } + +- if (idpf_is_queue_model_split(vport->rxq_model)) { +- for (j = 0; j < vport->num_bufqs_per_qgrp; j++) { ++ if (split) { ++ for (u32 j = 0; j < vport->num_bufqs_per_qgrp; j++) { ++ struct idpf_buf_queue *bufq; ++ + bufq = &rx_qgrp->splitq.bufq_sets[j].bufq; +- bufq->q_vector = &vport->q_vectors[bufq_vidx]; ++ bufq->q_vector = &vport->q_vectors[qv_idx]; + q_index = bufq->q_vector->num_bufq; + bufq->q_vector->bufq[q_index] = bufq; + bufq->q_vector->num_bufq++; + } +- if (++bufq_vidx >= vport->num_q_vectors) +- bufq_vidx = 0; + } ++ ++ qv_idx++; + } + ++ split = idpf_is_queue_model_split(vport->txq_model); ++ + for (i = 0, qv_idx = 0; i < num_txq_grp; i++) { + u16 num_txq; + ++ if (qv_idx >= vport->num_q_vectors) ++ qv_idx = 0; ++ + tx_qgrp = &vport->txq_grps[i]; + num_txq = tx_qgrp->num_txq; + +- if (idpf_is_queue_model_split(vport->txq_model)) { +- if (qv_idx >= vport->num_q_vectors) +- qv_idx = 0; ++ for (u32 j = 0; j < num_txq; j++) { ++ struct idpf_tx_queue *q; + +- q = tx_qgrp->complq; ++ q = tx_qgrp->txqs[j]; + q->q_vector = &vport->q_vectors[qv_idx]; +- q_index = q->q_vector->num_txq; +- q->q_vector->tx[q_index] = q; +- q->q_vector->num_txq++; +- qv_idx++; +- } else { +- for (j = 0; j < num_txq; j++) { +- if (qv_idx >= vport->num_q_vectors) +- qv_idx = 0; ++ q->q_vector->tx[q->q_vector->num_txq++] = q; ++ } + +- q = tx_qgrp->txqs[j]; +- q->q_vector = &vport->q_vectors[qv_idx]; +- q_index = q->q_vector->num_txq; +- q->q_vector->tx[q_index] = q; +- q->q_vector->num_txq++; ++ if (split) { ++ struct idpf_compl_queue *q = tx_qgrp->complq; + +- qv_idx++; +- } ++ q->q_vector = &vport->q_vectors[qv_idx]; ++ q->q_vector->complq[q->q_vector->num_complq++] = q; + } ++ ++ qv_idx++; + } + } + +@@ -4081,18 +4238,22 @@ int idpf_vport_intr_alloc(struct idpf_vport *vport) + { + u16 txqs_per_vector, rxqs_per_vector, bufqs_per_vector; + struct idpf_q_vector *q_vector; +- int v_idx, err; ++ u32 complqs_per_vector, v_idx; + + vport->q_vectors = kcalloc(vport->num_q_vectors, + sizeof(struct idpf_q_vector), GFP_KERNEL); + if (!vport->q_vectors) + return -ENOMEM; + +- txqs_per_vector = DIV_ROUND_UP(vport->num_txq, vport->num_q_vectors); +- rxqs_per_vector = DIV_ROUND_UP(vport->num_rxq, vport->num_q_vectors); ++ txqs_per_vector = DIV_ROUND_UP(vport->num_txq_grp, ++ vport->num_q_vectors); ++ rxqs_per_vector = DIV_ROUND_UP(vport->num_rxq_grp, ++ vport->num_q_vectors); + bufqs_per_vector = vport->num_bufqs_per_qgrp * + DIV_ROUND_UP(vport->num_rxq_grp, + vport->num_q_vectors); ++ complqs_per_vector = DIV_ROUND_UP(vport->num_txq_grp, ++ vport->num_q_vectors); + + for (v_idx = 0; v_idx < vport->num_q_vectors; v_idx++) { + q_vector = &vport->q_vectors[v_idx]; +@@ -4106,32 +4267,30 @@ int idpf_vport_intr_alloc(struct idpf_vport *vport) + q_vector->rx_intr_mode = IDPF_ITR_DYNAMIC; + q_vector->rx_itr_idx = VIRTCHNL2_ITR_IDX_0; + +- q_vector->tx = kcalloc(txqs_per_vector, +- sizeof(struct idpf_queue *), ++ q_vector->tx = kcalloc(txqs_per_vector, sizeof(*q_vector->tx), + GFP_KERNEL); +- if (!q_vector->tx) { +- err = -ENOMEM; ++ if (!q_vector->tx) + goto error; +- } + +- q_vector->rx = kcalloc(rxqs_per_vector, +- sizeof(struct idpf_queue *), ++ q_vector->rx = kcalloc(rxqs_per_vector, sizeof(*q_vector->rx), + GFP_KERNEL); +- if (!q_vector->rx) { +- err = -ENOMEM; ++ if (!q_vector->rx) + goto error; +- } + + if (!idpf_is_queue_model_split(vport->rxq_model)) + continue; + + q_vector->bufq = kcalloc(bufqs_per_vector, +- sizeof(struct idpf_queue *), ++ sizeof(*q_vector->bufq), + GFP_KERNEL); +- if (!q_vector->bufq) { +- err = -ENOMEM; ++ if (!q_vector->bufq) ++ goto error; ++ ++ q_vector->complq = kcalloc(complqs_per_vector, ++ sizeof(*q_vector->complq), ++ GFP_KERNEL); ++ if (!q_vector->complq) + goto error; +- } + } + + return 0; +@@ -4139,7 +4298,7 @@ int idpf_vport_intr_alloc(struct idpf_vport *vport) + error: + idpf_vport_intr_rel(vport); + +- return err; ++ return -ENOMEM; + } + + /** +diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.h b/drivers/net/ethernet/intel/idpf/idpf_txrx.h +index 551391e2046470..214a24e684634a 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.h ++++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.h +@@ -4,10 +4,13 @@ + #ifndef _IDPF_TXRX_H_ + #define _IDPF_TXRX_H_ + ++#include <linux/dim.h> ++ + #include <net/page_pool/helpers.h> + #include <net/tcp.h> + #include <net/netdev_queues.h> + ++#include "idpf_lan_txrx.h" + #include "virtchnl2_lan_desc.h" + + #define IDPF_LARGE_MAX_Q 256 +@@ -83,7 +86,7 @@ + do { \ + if (unlikely(++(ntc) == (rxq)->desc_count)) { \ + ntc = 0; \ +- change_bit(__IDPF_Q_GEN_CHK, (rxq)->flags); \ ++ idpf_queue_change(GEN_CHK, rxq); \ + } \ + } while (0) + +@@ -110,36 +113,17 @@ do { \ + */ + #define IDPF_TX_SPLITQ_RE_MIN_GAP 64 + +-#define IDPF_RX_BI_BUFID_S 0 +-#define IDPF_RX_BI_BUFID_M GENMASK(14, 0) +-#define IDPF_RX_BI_GEN_S 15 +-#define IDPF_RX_BI_GEN_M BIT(IDPF_RX_BI_GEN_S) ++#define IDPF_RX_BI_GEN_M BIT(16) ++#define IDPF_RX_BI_BUFID_M GENMASK(15, 0) ++ + #define IDPF_RXD_EOF_SPLITQ VIRTCHNL2_RX_FLEX_DESC_ADV_STATUS0_EOF_M + #define IDPF_RXD_EOF_SINGLEQ VIRTCHNL2_RX_BASE_DESC_STATUS_EOF_M + +-#define IDPF_SINGLEQ_RX_BUF_DESC(rxq, i) \ +- (&(((struct virtchnl2_singleq_rx_buf_desc *)((rxq)->desc_ring))[i])) +-#define IDPF_SPLITQ_RX_BUF_DESC(rxq, i) \ +- (&(((struct virtchnl2_splitq_rx_buf_desc *)((rxq)->desc_ring))[i])) +-#define IDPF_SPLITQ_RX_BI_DESC(rxq, i) ((((rxq)->ring))[i]) +- +-#define IDPF_BASE_TX_DESC(txq, i) \ +- (&(((struct idpf_base_tx_desc *)((txq)->desc_ring))[i])) +-#define IDPF_BASE_TX_CTX_DESC(txq, i) \ +- (&(((struct idpf_base_tx_ctx_desc *)((txq)->desc_ring))[i])) +-#define IDPF_SPLITQ_TX_COMPLQ_DESC(txcq, i) \ +- (&(((struct idpf_splitq_tx_compl_desc *)((txcq)->desc_ring))[i])) +- +-#define IDPF_FLEX_TX_DESC(txq, i) \ +- (&(((union idpf_tx_flex_desc *)((txq)->desc_ring))[i])) +-#define IDPF_FLEX_TX_CTX_DESC(txq, i) \ +- (&(((struct idpf_flex_tx_ctx_desc *)((txq)->desc_ring))[i])) +- + #define IDPF_DESC_UNUSED(txq) \ + ((((txq)->next_to_clean > (txq)->next_to_use) ? 0 : (txq)->desc_count) + \ + (txq)->next_to_clean - (txq)->next_to_use - 1) + +-#define IDPF_TX_BUF_RSV_UNUSED(txq) ((txq)->buf_stack.top) ++#define IDPF_TX_BUF_RSV_UNUSED(txq) ((txq)->stash->buf_stack.top) + #define IDPF_TX_BUF_RSV_LOW(txq) (IDPF_TX_BUF_RSV_UNUSED(txq) < \ + (txq)->desc_count >> 2) + +@@ -317,8 +301,6 @@ struct idpf_rx_extracted { + + #define IDPF_RX_DMA_ATTR \ + (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING) +-#define IDPF_RX_DESC(rxq, i) \ +- (&(((union virtchnl2_rx_desc *)((rxq)->desc_ring))[i])) + + struct idpf_rx_buf { + struct page *page; +@@ -452,23 +434,37 @@ struct idpf_rx_ptype_decoded { + * to 1 and knows that reading a gen bit of 1 in any + * descriptor on the initial pass of the ring indicates a + * writeback. It also flips on every ring wrap. +- * @__IDPF_RFLQ_GEN_CHK: Refill queues are SW only, so Q_GEN acts as the HW bit +- * and RFLGQ_GEN is the SW bit. ++ * @__IDPF_Q_RFL_GEN_CHK: Refill queues are SW only, so Q_GEN acts as the HW ++ * bit and Q_RFL_GEN is the SW bit. + * @__IDPF_Q_FLOW_SCH_EN: Enable flow scheduling + * @__IDPF_Q_SW_MARKER: Used to indicate TX queue marker completions + * @__IDPF_Q_POLL_MODE: Enable poll mode ++ * @__IDPF_Q_CRC_EN: enable CRC offload in singleq mode ++ * @__IDPF_Q_HSPLIT_EN: enable header split on Rx (splitq) + * @__IDPF_Q_FLAGS_NBITS: Must be last + */ + enum idpf_queue_flags_t { + __IDPF_Q_GEN_CHK, +- __IDPF_RFLQ_GEN_CHK, ++ __IDPF_Q_RFL_GEN_CHK, + __IDPF_Q_FLOW_SCH_EN, + __IDPF_Q_SW_MARKER, + __IDPF_Q_POLL_MODE, ++ __IDPF_Q_CRC_EN, ++ __IDPF_Q_HSPLIT_EN, + + __IDPF_Q_FLAGS_NBITS, + }; + ++#define idpf_queue_set(f, q) __set_bit(__IDPF_Q_##f, (q)->flags) ++#define idpf_queue_clear(f, q) __clear_bit(__IDPF_Q_##f, (q)->flags) ++#define idpf_queue_change(f, q) __change_bit(__IDPF_Q_##f, (q)->flags) ++#define idpf_queue_has(f, q) test_bit(__IDPF_Q_##f, (q)->flags) ++ ++#define idpf_queue_has_clear(f, q) \ ++ __test_and_clear_bit(__IDPF_Q_##f, (q)->flags) ++#define idpf_queue_assign(f, q, v) \ ++ __assign_bit(__IDPF_Q_##f, (q)->flags, v) ++ + /** + * struct idpf_vec_regs + * @dyn_ctl_reg: Dynamic control interrupt register offset +@@ -514,7 +510,9 @@ struct idpf_intr_reg { + * @v_idx: Vector index + * @intr_reg: See struct idpf_intr_reg + * @num_txq: Number of TX queues ++ * @num_complq: number of completion queues + * @tx: Array of TX queues to service ++ * @complq: array of completion queues + * @tx_dim: Data for TX net_dim algorithm + * @tx_itr_value: TX interrupt throttling rate + * @tx_intr_mode: Dynamic ITR or not +@@ -538,21 +536,24 @@ struct idpf_q_vector { + struct idpf_intr_reg intr_reg; + + u16 num_txq; +- struct idpf_queue **tx; ++ u16 num_complq; ++ struct idpf_tx_queue **tx; ++ struct idpf_compl_queue **complq; ++ + struct dim tx_dim; + u16 tx_itr_value; + bool tx_intr_mode; + u32 tx_itr_idx; + + u16 num_rxq; +- struct idpf_queue **rx; ++ struct idpf_rx_queue **rx; + struct dim rx_dim; + u16 rx_itr_value; + bool rx_intr_mode; + u32 rx_itr_idx; + + u16 num_bufq; +- struct idpf_queue **bufq; ++ struct idpf_buf_queue **bufq; + + u16 total_events; + char *name; +@@ -583,11 +584,6 @@ struct idpf_cleaned_stats { + u32 bytes; + }; + +-union idpf_queue_stats { +- struct idpf_rx_queue_stats rx; +- struct idpf_tx_queue_stats tx; +-}; +- + #define IDPF_ITR_DYNAMIC 1 + #define IDPF_ITR_MAX 0x1FE0 + #define IDPF_ITR_20K 0x0032 +@@ -603,39 +599,114 @@ union idpf_queue_stats { + #define IDPF_DIM_DEFAULT_PROFILE_IX 1 + + /** +- * struct idpf_queue +- * @dev: Device back pointer for DMA mapping +- * @vport: Back pointer to associated vport +- * @txq_grp: See struct idpf_txq_group +- * @rxq_grp: See struct idpf_rxq_group +- * @idx: For buffer queue, it is used as group id, either 0 or 1. On clean, +- * buffer queue uses this index to determine which group of refill queues +- * to clean. +- * For TX queue, it is used as index to map between TX queue group and +- * hot path TX pointers stored in vport. Used in both singleq/splitq. +- * For RX queue, it is used to index to total RX queue across groups and ++ * struct idpf_txq_stash - Tx buffer stash for Flow-based scheduling mode ++ * @buf_stack: Stack of empty buffers to store buffer info for out of order ++ * buffer completions. See struct idpf_buf_lifo ++ * @sched_buf_hash: Hash table to store buffers ++ */ ++struct idpf_txq_stash { ++ struct idpf_buf_lifo buf_stack; ++ DECLARE_HASHTABLE(sched_buf_hash, 12); ++} ____cacheline_aligned; ++ ++/** ++ * struct idpf_rx_queue - software structure representing a receive queue ++ * @rx: universal receive descriptor array ++ * @single_buf: buffer descriptor array in singleq ++ * @desc_ring: virtual descriptor ring address ++ * @bufq_sets: Pointer to the array of buffer queues in splitq mode ++ * @napi: NAPI instance corresponding to this queue (splitq) ++ * @rx_buf: See struct idpf_rx_buf ++ * @pp: Page pool pointer in singleq mode ++ * @netdev: &net_device corresponding to this queue ++ * @tail: Tail offset. Used for both queue models single and split. ++ * @flags: See enum idpf_queue_flags_t ++ * @idx: For RX queue, it is used to index to total RX queue across groups and + * used for skb reporting. +- * @tail: Tail offset. Used for both queue models single and split. In splitq +- * model relevant only for TX queue and RX queue. +- * @tx_buf: See struct idpf_tx_buf +- * @rx_buf: Struct with RX buffer related members +- * @rx_buf.buf: See struct idpf_rx_buf +- * @rx_buf.hdr_buf_pa: DMA handle +- * @rx_buf.hdr_buf_va: Virtual address +- * @pp: Page pool pointer ++ * @desc_count: Number of descriptors ++ * @next_to_use: Next descriptor to use ++ * @next_to_clean: Next descriptor to clean ++ * @next_to_alloc: RX buffer to allocate at ++ * @rxdids: Supported RX descriptor ids ++ * @rx_ptype_lkup: LUT of Rx ptypes + * @skb: Pointer to the skb +- * @q_type: Queue type (TX, RX, TX completion, RX buffer) ++ * @stats_sync: See struct u64_stats_sync ++ * @q_stats: See union idpf_rx_queue_stats + * @q_id: Queue id +- * @desc_count: Number of descriptors +- * @next_to_use: Next descriptor to use. Relevant in both split & single txq +- * and bufq. +- * @next_to_clean: Next descriptor to clean. In split queue model, only +- * relevant to TX completion queue and RX queue. +- * @next_to_alloc: RX buffer to allocate at. Used only for RX. In splitq model +- * only relevant to RX queue. ++ * @size: Length of descriptor ring in bytes ++ * @dma: Physical address of ring ++ * @q_vector: Backreference to associated vector ++ * @rx_buffer_low_watermark: RX buffer low watermark ++ * @rx_hbuf_size: Header buffer size ++ * @rx_buf_size: Buffer size ++ * @rx_max_pkt_size: RX max packet size ++ */ ++struct idpf_rx_queue { ++ union { ++ union virtchnl2_rx_desc *rx; ++ struct virtchnl2_singleq_rx_buf_desc *single_buf; ++ ++ void *desc_ring; ++ }; ++ union { ++ struct { ++ struct idpf_bufq_set *bufq_sets; ++ struct napi_struct *napi; ++ }; ++ struct { ++ struct idpf_rx_buf *rx_buf; ++ struct page_pool *pp; ++ }; ++ }; ++ struct net_device *netdev; ++ void __iomem *tail; ++ ++ DECLARE_BITMAP(flags, __IDPF_Q_FLAGS_NBITS); ++ u16 idx; ++ u16 desc_count; ++ u16 next_to_use; ++ u16 next_to_clean; ++ u16 next_to_alloc; ++ ++ u32 rxdids; ++ ++ const struct idpf_rx_ptype_decoded *rx_ptype_lkup; ++ struct sk_buff *skb; ++ ++ struct u64_stats_sync stats_sync; ++ struct idpf_rx_queue_stats q_stats; ++ ++ /* Slowpath */ ++ u32 q_id; ++ u32 size; ++ dma_addr_t dma; ++ ++ struct idpf_q_vector *q_vector; ++ ++ u16 rx_buffer_low_watermark; ++ u16 rx_hbuf_size; ++ u16 rx_buf_size; ++ u16 rx_max_pkt_size; ++} ____cacheline_aligned; ++ ++/** ++ * struct idpf_tx_queue - software structure representing a transmit queue ++ * @base_tx: base Tx descriptor array ++ * @base_ctx: base Tx context descriptor array ++ * @flex_tx: flex Tx descriptor array ++ * @flex_ctx: flex Tx context descriptor array ++ * @desc_ring: virtual descriptor ring address ++ * @tx_buf: See struct idpf_tx_buf ++ * @txq_grp: See struct idpf_txq_group ++ * @dev: Device back pointer for DMA mapping ++ * @tail: Tail offset. Used for both queue models single and split + * @flags: See enum idpf_queue_flags_t +- * @q_stats: See union idpf_queue_stats +- * @stats_sync: See struct u64_stats_sync ++ * @idx: For TX queue, it is used as index to map between TX queue group and ++ * hot path TX pointers stored in vport. Used in both singleq/splitq. ++ * @desc_count: Number of descriptors ++ * @next_to_use: Next descriptor to use ++ * @next_to_clean: Next descriptor to clean ++ * @netdev: &net_device corresponding to this queue + * @cleaned_bytes: Splitq only, TXQ only: When a TX completion is received on + * the TX completion queue, it can be for any TXQ associated + * with that completion queue. This means we can clean up to +@@ -644,26 +715,10 @@ union idpf_queue_stats { + * that single call to clean the completion queue. By doing so, + * we can update BQL with aggregate cleaned stats for each TXQ + * only once at the end of the cleaning routine. ++ * @clean_budget: singleq only, queue cleaning budget + * @cleaned_pkts: Number of packets cleaned for the above said case +- * @rx_hsplit_en: RX headsplit enable +- * @rx_hbuf_size: Header buffer size +- * @rx_buf_size: Buffer size +- * @rx_max_pkt_size: RX max packet size +- * @rx_buf_stride: RX buffer stride +- * @rx_buffer_low_watermark: RX buffer low watermark +- * @rxdids: Supported RX descriptor ids +- * @q_vector: Backreference to associated vector +- * @size: Length of descriptor ring in bytes +- * @dma: Physical address of ring +- * @desc_ring: Descriptor ring memory + * @tx_max_bufs: Max buffers that can be transmitted with scatter-gather + * @tx_min_pkt_len: Min supported packet length +- * @num_completions: Only relevant for TX completion queue. It tracks the +- * number of completions received to compare against the +- * number of completions pending, as accumulated by the +- * TX queues. +- * @buf_stack: Stack of empty buffers to store buffer info for out of order +- * buffer completions. See struct idpf_buf_lifo. + * @compl_tag_bufid_m: Completion tag buffer id mask + * @compl_tag_gen_s: Completion tag generation bit + * The format of the completion tag will change based on the TXQ +@@ -687,106 +742,188 @@ union idpf_queue_stats { + * This gives us 8*8160 = 65280 possible unique values. + * @compl_tag_cur_gen: Used to keep track of current completion tag generation + * @compl_tag_gen_max: To determine when compl_tag_cur_gen should be reset +- * @sched_buf_hash: Hash table to stores buffers ++ * @stash: Tx buffer stash for Flow-based scheduling mode ++ * @stats_sync: See struct u64_stats_sync ++ * @q_stats: See union idpf_tx_queue_stats ++ * @q_id: Queue id ++ * @size: Length of descriptor ring in bytes ++ * @dma: Physical address of ring ++ * @q_vector: Backreference to associated vector + */ +-struct idpf_queue { +- struct device *dev; +- struct idpf_vport *vport; ++struct idpf_tx_queue { + union { +- struct idpf_txq_group *txq_grp; +- struct idpf_rxq_group *rxq_grp; ++ struct idpf_base_tx_desc *base_tx; ++ struct idpf_base_tx_ctx_desc *base_ctx; ++ union idpf_tx_flex_desc *flex_tx; ++ struct idpf_flex_tx_ctx_desc *flex_ctx; ++ ++ void *desc_ring; + }; +- u16 idx; ++ struct idpf_tx_buf *tx_buf; ++ struct idpf_txq_group *txq_grp; ++ struct device *dev; + void __iomem *tail; ++ ++ DECLARE_BITMAP(flags, __IDPF_Q_FLAGS_NBITS); ++ u16 idx; ++ u16 desc_count; ++ u16 next_to_use; ++ u16 next_to_clean; ++ ++ struct net_device *netdev; ++ + union { +- struct idpf_tx_buf *tx_buf; +- struct { +- struct idpf_rx_buf *buf; +- dma_addr_t hdr_buf_pa; +- void *hdr_buf_va; +- } rx_buf; ++ u32 cleaned_bytes; ++ u32 clean_budget; + }; +- struct page_pool *pp; +- struct sk_buff *skb; +- u16 q_type; ++ u16 cleaned_pkts; ++ ++ u16 tx_max_bufs; ++ u16 tx_min_pkt_len; ++ ++ u16 compl_tag_bufid_m; ++ u16 compl_tag_gen_s; ++ ++ u16 compl_tag_cur_gen; ++ u16 compl_tag_gen_max; ++ ++ struct idpf_txq_stash *stash; ++ ++ struct u64_stats_sync stats_sync; ++ struct idpf_tx_queue_stats q_stats; ++ ++ /* Slowpath */ + u32 q_id; +- u16 desc_count; ++ u32 size; ++ dma_addr_t dma; + ++ struct idpf_q_vector *q_vector; ++} ____cacheline_aligned; ++ ++/** ++ * struct idpf_buf_queue - software structure representing a buffer queue ++ * @split_buf: buffer descriptor array ++ * @rx_buf: Struct with RX buffer related members ++ * @rx_buf.buf: See struct idpf_rx_buf ++ * @rx_buf.hdr_buf_pa: DMA handle ++ * @rx_buf.hdr_buf_va: Virtual address ++ * @pp: Page pool pointer ++ * @tail: Tail offset ++ * @flags: See enum idpf_queue_flags_t ++ * @desc_count: Number of descriptors ++ * @next_to_use: Next descriptor to use ++ * @next_to_clean: Next descriptor to clean ++ * @next_to_alloc: RX buffer to allocate at ++ * @q_id: Queue id ++ * @size: Length of descriptor ring in bytes ++ * @dma: Physical address of ring ++ * @q_vector: Backreference to associated vector ++ * @rx_buffer_low_watermark: RX buffer low watermark ++ * @rx_hbuf_size: Header buffer size ++ * @rx_buf_size: Buffer size ++ */ ++struct idpf_buf_queue { ++ struct virtchnl2_splitq_rx_buf_desc *split_buf; ++ struct { ++ struct idpf_rx_buf *buf; ++ dma_addr_t hdr_buf_pa; ++ void *hdr_buf_va; ++ } rx_buf; ++ struct page_pool *pp; ++ void __iomem *tail; ++ ++ DECLARE_BITMAP(flags, __IDPF_Q_FLAGS_NBITS); ++ u16 desc_count; + u16 next_to_use; + u16 next_to_clean; + u16 next_to_alloc; +- DECLARE_BITMAP(flags, __IDPF_Q_FLAGS_NBITS); + +- union idpf_queue_stats q_stats; +- struct u64_stats_sync stats_sync; ++ /* Slowpath */ ++ u32 q_id; ++ u32 size; ++ dma_addr_t dma; + +- u32 cleaned_bytes; +- u16 cleaned_pkts; ++ struct idpf_q_vector *q_vector; + +- bool rx_hsplit_en; ++ u16 rx_buffer_low_watermark; + u16 rx_hbuf_size; + u16 rx_buf_size; +- u16 rx_max_pkt_size; +- u16 rx_buf_stride; +- u8 rx_buffer_low_watermark; +- u64 rxdids; +- struct idpf_q_vector *q_vector; +- unsigned int size; +- dma_addr_t dma; +- void *desc_ring; +- +- u16 tx_max_bufs; +- u8 tx_min_pkt_len; ++} ____cacheline_aligned; + +- u32 num_completions; ++/** ++ * struct idpf_compl_queue - software structure representing a completion queue ++ * @comp: completion descriptor array ++ * @txq_grp: See struct idpf_txq_group ++ * @flags: See enum idpf_queue_flags_t ++ * @desc_count: Number of descriptors ++ * @next_to_use: Next descriptor to use. Relevant in both split & single txq ++ * and bufq. ++ * @next_to_clean: Next descriptor to clean ++ * @netdev: &net_device corresponding to this queue ++ * @clean_budget: queue cleaning budget ++ * @num_completions: Only relevant for TX completion queue. It tracks the ++ * number of completions received to compare against the ++ * number of completions pending, as accumulated by the ++ * TX queues. ++ * @q_id: Queue id ++ * @size: Length of descriptor ring in bytes ++ * @dma: Physical address of ring ++ * @q_vector: Backreference to associated vector ++ */ ++struct idpf_compl_queue { ++ struct idpf_splitq_tx_compl_desc *comp; ++ struct idpf_txq_group *txq_grp; + +- struct idpf_buf_lifo buf_stack; ++ DECLARE_BITMAP(flags, __IDPF_Q_FLAGS_NBITS); ++ u16 desc_count; ++ u16 next_to_use; ++ u16 next_to_clean; + +- u16 compl_tag_bufid_m; +- u16 compl_tag_gen_s; ++ struct net_device *netdev; ++ u32 clean_budget; ++ u32 num_completions; + +- u16 compl_tag_cur_gen; +- u16 compl_tag_gen_max; ++ /* Slowpath */ ++ u32 q_id; ++ u32 size; ++ dma_addr_t dma; + +- DECLARE_HASHTABLE(sched_buf_hash, 12); +-} ____cacheline_internodealigned_in_smp; ++ struct idpf_q_vector *q_vector; ++} ____cacheline_aligned; + + /** + * struct idpf_sw_queue +- * @next_to_clean: Next descriptor to clean +- * @next_to_alloc: Buffer to allocate at +- * @flags: See enum idpf_queue_flags_t + * @ring: Pointer to the ring ++ * @flags: See enum idpf_queue_flags_t + * @desc_count: Descriptor count +- * @dev: Device back pointer for DMA mapping ++ * @next_to_use: Buffer to allocate at ++ * @next_to_clean: Next descriptor to clean + * + * Software queues are used in splitq mode to manage buffers between rxq + * producer and the bufq consumer. These are required in order to maintain a + * lockless buffer management system and are strictly software only constructs. + */ + struct idpf_sw_queue { +- u16 next_to_clean; +- u16 next_to_alloc; ++ u32 *ring; ++ + DECLARE_BITMAP(flags, __IDPF_Q_FLAGS_NBITS); +- u16 *ring; + u16 desc_count; +- struct device *dev; +-} ____cacheline_internodealigned_in_smp; ++ u16 next_to_use; ++ u16 next_to_clean; ++} ____cacheline_aligned; + + /** + * struct idpf_rxq_set + * @rxq: RX queue +- * @refillq0: Pointer to refill queue 0 +- * @refillq1: Pointer to refill queue 1 ++ * @refillq: pointers to refill queues + * + * Splitq only. idpf_rxq_set associates an rxq with at an array of refillqs. + * Each rxq needs a refillq to return used buffers back to the respective bufq. + * Bufqs then clean these refillqs for buffers to give to hardware. + */ + struct idpf_rxq_set { +- struct idpf_queue rxq; +- struct idpf_sw_queue *refillq0; +- struct idpf_sw_queue *refillq1; ++ struct idpf_rx_queue rxq; ++ struct idpf_sw_queue *refillq[IDPF_MAX_BUFQS_PER_RXQ_GRP]; + }; + + /** +@@ -805,7 +942,7 @@ struct idpf_rxq_set { + * managed by at most two bufqs (depending on performance configuration). + */ + struct idpf_bufq_set { +- struct idpf_queue bufq; ++ struct idpf_buf_queue bufq; + int num_refillqs; + struct idpf_sw_queue *refillqs; + }; +@@ -831,7 +968,7 @@ struct idpf_rxq_group { + union { + struct { + u16 num_rxq; +- struct idpf_queue *rxqs[IDPF_LARGE_MAX_Q]; ++ struct idpf_rx_queue *rxqs[IDPF_LARGE_MAX_Q]; + } singleq; + struct { + u16 num_rxq_sets; +@@ -846,6 +983,7 @@ struct idpf_rxq_group { + * @vport: Vport back pointer + * @num_txq: Number of TX queues associated + * @txqs: Array of TX queue pointers ++ * @stashes: array of OOO stashes for the queues + * @complq: Associated completion queue pointer, split queue only + * @num_completions_pending: Total number of completions pending for the + * completion queue, acculumated for all TX queues +@@ -859,9 +997,10 @@ struct idpf_txq_group { + struct idpf_vport *vport; + + u16 num_txq; +- struct idpf_queue *txqs[IDPF_LARGE_MAX_Q]; ++ struct idpf_tx_queue *txqs[IDPF_LARGE_MAX_Q]; ++ struct idpf_txq_stash *stashes; + +- struct idpf_queue *complq; ++ struct idpf_compl_queue *complq; + + u32 num_completions_pending; + }; +@@ -998,29 +1137,31 @@ void idpf_deinit_rss(struct idpf_vport *vport); + int idpf_rx_bufs_init_all(struct idpf_vport *vport); + void idpf_rx_add_frag(struct idpf_rx_buf *rx_buf, struct sk_buff *skb, + unsigned int size); +-struct sk_buff *idpf_rx_construct_skb(struct idpf_queue *rxq, ++struct sk_buff *idpf_rx_construct_skb(const struct idpf_rx_queue *rxq, + struct idpf_rx_buf *rx_buf, + unsigned int size); +-bool idpf_init_rx_buf_hw_alloc(struct idpf_queue *rxq, struct idpf_rx_buf *buf); +-void idpf_rx_buf_hw_update(struct idpf_queue *rxq, u32 val); +-void idpf_tx_buf_hw_update(struct idpf_queue *tx_q, u32 val, ++void idpf_tx_buf_hw_update(struct idpf_tx_queue *tx_q, u32 val, + bool xmit_more); + unsigned int idpf_size_to_txd_count(unsigned int size); +-netdev_tx_t idpf_tx_drop_skb(struct idpf_queue *tx_q, struct sk_buff *skb); +-void idpf_tx_dma_map_error(struct idpf_queue *txq, struct sk_buff *skb, ++netdev_tx_t idpf_tx_drop_skb(struct idpf_tx_queue *tx_q, struct sk_buff *skb); ++void idpf_tx_dma_map_error(struct idpf_tx_queue *txq, struct sk_buff *skb, + struct idpf_tx_buf *first, u16 ring_idx); +-unsigned int idpf_tx_desc_count_required(struct idpf_queue *txq, ++unsigned int idpf_tx_desc_count_required(struct idpf_tx_queue *txq, + struct sk_buff *skb); +-bool idpf_chk_linearize(struct sk_buff *skb, unsigned int max_bufs, +- unsigned int count); +-int idpf_tx_maybe_stop_common(struct idpf_queue *tx_q, unsigned int size); + void idpf_tx_timeout(struct net_device *netdev, unsigned int txqueue); +-netdev_tx_t idpf_tx_splitq_start(struct sk_buff *skb, +- struct net_device *netdev); +-netdev_tx_t idpf_tx_singleq_start(struct sk_buff *skb, +- struct net_device *netdev); +-bool idpf_rx_singleq_buf_hw_alloc_all(struct idpf_queue *rxq, ++netdev_tx_t idpf_tx_singleq_frame(struct sk_buff *skb, ++ struct idpf_tx_queue *tx_q); ++netdev_tx_t idpf_tx_start(struct sk_buff *skb, struct net_device *netdev); ++bool idpf_rx_singleq_buf_hw_alloc_all(struct idpf_rx_queue *rxq, + u16 cleaned_count); + int idpf_tso(struct sk_buff *skb, struct idpf_tx_offload_params *off); + ++static inline bool idpf_tx_maybe_stop_common(struct idpf_tx_queue *tx_q, ++ u32 needed) ++{ ++ return !netif_subqueue_maybe_stop(tx_q->netdev, tx_q->idx, ++ IDPF_DESC_UNUSED(tx_q), ++ needed, needed); ++} ++ + #endif /* !_IDPF_TXRX_H_ */ +diff --git a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c +index a5f9b7a5effe7b..44602b87cd4114 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c ++++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c +@@ -750,7 +750,7 @@ static int idpf_wait_for_marker_event(struct idpf_vport *vport) + int i; + + for (i = 0; i < vport->num_txq; i++) +- set_bit(__IDPF_Q_SW_MARKER, vport->txqs[i]->flags); ++ idpf_queue_set(SW_MARKER, vport->txqs[i]); + + event = wait_event_timeout(vport->sw_marker_wq, + test_and_clear_bit(IDPF_VPORT_SW_MARKER, +@@ -758,7 +758,7 @@ static int idpf_wait_for_marker_event(struct idpf_vport *vport) + msecs_to_jiffies(500)); + + for (i = 0; i < vport->num_txq; i++) +- clear_bit(__IDPF_Q_POLL_MODE, vport->txqs[i]->flags); ++ idpf_queue_clear(POLL_MODE, vport->txqs[i]); + + if (event) + return 0; +@@ -1092,7 +1092,6 @@ static int __idpf_queue_reg_init(struct idpf_vport *vport, u32 *reg_vals, + int num_regs, u32 q_type) + { + struct idpf_adapter *adapter = vport->adapter; +- struct idpf_queue *q; + int i, j, k = 0; + + switch (q_type) { +@@ -1111,6 +1110,8 @@ static int __idpf_queue_reg_init(struct idpf_vport *vport, u32 *reg_vals, + u16 num_rxq = rx_qgrp->singleq.num_rxq; + + for (j = 0; j < num_rxq && k < num_regs; j++, k++) { ++ struct idpf_rx_queue *q; ++ + q = rx_qgrp->singleq.rxqs[j]; + q->tail = idpf_get_reg_addr(adapter, + reg_vals[k]); +@@ -1123,6 +1124,8 @@ static int __idpf_queue_reg_init(struct idpf_vport *vport, u32 *reg_vals, + u8 num_bufqs = vport->num_bufqs_per_qgrp; + + for (j = 0; j < num_bufqs && k < num_regs; j++, k++) { ++ struct idpf_buf_queue *q; ++ + q = &rx_qgrp->splitq.bufq_sets[j].bufq; + q->tail = idpf_get_reg_addr(adapter, + reg_vals[k]); +@@ -1449,19 +1452,19 @@ static int idpf_send_config_tx_queues_msg(struct idpf_vport *vport) + qi[k].model = + cpu_to_le16(vport->txq_model); + qi[k].type = +- cpu_to_le32(tx_qgrp->txqs[j]->q_type); ++ cpu_to_le32(VIRTCHNL2_QUEUE_TYPE_TX); + qi[k].ring_len = + cpu_to_le16(tx_qgrp->txqs[j]->desc_count); + qi[k].dma_ring_addr = + cpu_to_le64(tx_qgrp->txqs[j]->dma); + if (idpf_is_queue_model_split(vport->txq_model)) { +- struct idpf_queue *q = tx_qgrp->txqs[j]; ++ struct idpf_tx_queue *q = tx_qgrp->txqs[j]; + + qi[k].tx_compl_queue_id = + cpu_to_le16(tx_qgrp->complq->q_id); + qi[k].relative_queue_id = cpu_to_le16(j); + +- if (test_bit(__IDPF_Q_FLOW_SCH_EN, q->flags)) ++ if (idpf_queue_has(FLOW_SCH_EN, q)) + qi[k].sched_mode = + cpu_to_le16(VIRTCHNL2_TXQ_SCHED_MODE_FLOW); + else +@@ -1478,11 +1481,11 @@ static int idpf_send_config_tx_queues_msg(struct idpf_vport *vport) + + qi[k].queue_id = cpu_to_le32(tx_qgrp->complq->q_id); + qi[k].model = cpu_to_le16(vport->txq_model); +- qi[k].type = cpu_to_le32(tx_qgrp->complq->q_type); ++ qi[k].type = cpu_to_le32(VIRTCHNL2_QUEUE_TYPE_TX_COMPLETION); + qi[k].ring_len = cpu_to_le16(tx_qgrp->complq->desc_count); + qi[k].dma_ring_addr = cpu_to_le64(tx_qgrp->complq->dma); + +- if (test_bit(__IDPF_Q_FLOW_SCH_EN, tx_qgrp->complq->flags)) ++ if (idpf_queue_has(FLOW_SCH_EN, tx_qgrp->complq)) + sched_mode = VIRTCHNL2_TXQ_SCHED_MODE_FLOW; + else + sched_mode = VIRTCHNL2_TXQ_SCHED_MODE_QUEUE; +@@ -1567,17 +1570,18 @@ static int idpf_send_config_rx_queues_msg(struct idpf_vport *vport) + goto setup_rxqs; + + for (j = 0; j < vport->num_bufqs_per_qgrp; j++, k++) { +- struct idpf_queue *bufq = ++ struct idpf_buf_queue *bufq = + &rx_qgrp->splitq.bufq_sets[j].bufq; + + qi[k].queue_id = cpu_to_le32(bufq->q_id); + qi[k].model = cpu_to_le16(vport->rxq_model); +- qi[k].type = cpu_to_le32(bufq->q_type); ++ qi[k].type = ++ cpu_to_le32(VIRTCHNL2_QUEUE_TYPE_RX_BUFFER); + qi[k].desc_ids = cpu_to_le64(VIRTCHNL2_RXDID_2_FLEX_SPLITQ_M); + qi[k].ring_len = cpu_to_le16(bufq->desc_count); + qi[k].dma_ring_addr = cpu_to_le64(bufq->dma); + qi[k].data_buffer_size = cpu_to_le32(bufq->rx_buf_size); +- qi[k].buffer_notif_stride = bufq->rx_buf_stride; ++ qi[k].buffer_notif_stride = IDPF_RX_BUF_STRIDE; + qi[k].rx_buffer_low_watermark = + cpu_to_le16(bufq->rx_buffer_low_watermark); + if (idpf_is_feature_ena(vport, NETIF_F_GRO_HW)) +@@ -1591,7 +1595,7 @@ static int idpf_send_config_rx_queues_msg(struct idpf_vport *vport) + num_rxq = rx_qgrp->singleq.num_rxq; + + for (j = 0; j < num_rxq; j++, k++) { +- struct idpf_queue *rxq; ++ struct idpf_rx_queue *rxq; + + if (!idpf_is_queue_model_split(vport->rxq_model)) { + rxq = rx_qgrp->singleq.rxqs[j]; +@@ -1599,11 +1603,11 @@ static int idpf_send_config_rx_queues_msg(struct idpf_vport *vport) + } + rxq = &rx_qgrp->splitq.rxq_sets[j]->rxq; + qi[k].rx_bufq1_id = +- cpu_to_le16(rxq->rxq_grp->splitq.bufq_sets[0].bufq.q_id); ++ cpu_to_le16(rxq->bufq_sets[0].bufq.q_id); + if (vport->num_bufqs_per_qgrp > IDPF_SINGLE_BUFQ_PER_RXQ_GRP) { + qi[k].bufq2_ena = IDPF_BUFQ2_ENA; + qi[k].rx_bufq2_id = +- cpu_to_le16(rxq->rxq_grp->splitq.bufq_sets[1].bufq.q_id); ++ cpu_to_le16(rxq->bufq_sets[1].bufq.q_id); + } + qi[k].rx_buffer_low_watermark = + cpu_to_le16(rxq->rx_buffer_low_watermark); +@@ -1611,7 +1615,7 @@ static int idpf_send_config_rx_queues_msg(struct idpf_vport *vport) + qi[k].qflags |= cpu_to_le16(VIRTCHNL2_RXQ_RSC); + + common_qi_fields: +- if (rxq->rx_hsplit_en) { ++ if (idpf_queue_has(HSPLIT_EN, rxq)) { + qi[k].qflags |= + cpu_to_le16(VIRTCHNL2_RXQ_HDR_SPLIT); + qi[k].hdr_buffer_size = +@@ -1619,7 +1623,7 @@ static int idpf_send_config_rx_queues_msg(struct idpf_vport *vport) + } + qi[k].queue_id = cpu_to_le32(rxq->q_id); + qi[k].model = cpu_to_le16(vport->rxq_model); +- qi[k].type = cpu_to_le32(rxq->q_type); ++ qi[k].type = cpu_to_le32(VIRTCHNL2_QUEUE_TYPE_RX); + qi[k].ring_len = cpu_to_le16(rxq->desc_count); + qi[k].dma_ring_addr = cpu_to_le64(rxq->dma); + qi[k].max_pkt_size = cpu_to_le32(rxq->rx_max_pkt_size); +@@ -1706,7 +1710,7 @@ static int idpf_send_ena_dis_queues_msg(struct idpf_vport *vport, bool ena) + struct idpf_txq_group *tx_qgrp = &vport->txq_grps[i]; + + for (j = 0; j < tx_qgrp->num_txq; j++, k++) { +- qc[k].type = cpu_to_le32(tx_qgrp->txqs[j]->q_type); ++ qc[k].type = cpu_to_le32(VIRTCHNL2_QUEUE_TYPE_TX); + qc[k].start_queue_id = cpu_to_le32(tx_qgrp->txqs[j]->q_id); + qc[k].num_queues = cpu_to_le32(IDPF_NUMQ_PER_CHUNK); + } +@@ -1720,7 +1724,7 @@ static int idpf_send_ena_dis_queues_msg(struct idpf_vport *vport, bool ena) + for (i = 0; i < vport->num_txq_grp; i++, k++) { + struct idpf_txq_group *tx_qgrp = &vport->txq_grps[i]; + +- qc[k].type = cpu_to_le32(tx_qgrp->complq->q_type); ++ qc[k].type = cpu_to_le32(VIRTCHNL2_QUEUE_TYPE_TX_COMPLETION); + qc[k].start_queue_id = cpu_to_le32(tx_qgrp->complq->q_id); + qc[k].num_queues = cpu_to_le32(IDPF_NUMQ_PER_CHUNK); + } +@@ -1741,12 +1745,12 @@ static int idpf_send_ena_dis_queues_msg(struct idpf_vport *vport, bool ena) + qc[k].start_queue_id = + cpu_to_le32(rx_qgrp->splitq.rxq_sets[j]->rxq.q_id); + qc[k].type = +- cpu_to_le32(rx_qgrp->splitq.rxq_sets[j]->rxq.q_type); ++ cpu_to_le32(VIRTCHNL2_QUEUE_TYPE_RX); + } else { + qc[k].start_queue_id = + cpu_to_le32(rx_qgrp->singleq.rxqs[j]->q_id); + qc[k].type = +- cpu_to_le32(rx_qgrp->singleq.rxqs[j]->q_type); ++ cpu_to_le32(VIRTCHNL2_QUEUE_TYPE_RX); + } + qc[k].num_queues = cpu_to_le32(IDPF_NUMQ_PER_CHUNK); + } +@@ -1761,10 +1765,11 @@ static int idpf_send_ena_dis_queues_msg(struct idpf_vport *vport, bool ena) + struct idpf_rxq_group *rx_qgrp = &vport->rxq_grps[i]; + + for (j = 0; j < vport->num_bufqs_per_qgrp; j++, k++) { +- struct idpf_queue *q; ++ const struct idpf_buf_queue *q; + + q = &rx_qgrp->splitq.bufq_sets[j].bufq; +- qc[k].type = cpu_to_le32(q->q_type); ++ qc[k].type = ++ cpu_to_le32(VIRTCHNL2_QUEUE_TYPE_RX_BUFFER); + qc[k].start_queue_id = cpu_to_le32(q->q_id); + qc[k].num_queues = cpu_to_le32(IDPF_NUMQ_PER_CHUNK); + } +@@ -1849,7 +1854,8 @@ int idpf_send_map_unmap_queue_vector_msg(struct idpf_vport *vport, bool map) + struct idpf_txq_group *tx_qgrp = &vport->txq_grps[i]; + + for (j = 0; j < tx_qgrp->num_txq; j++, k++) { +- vqv[k].queue_type = cpu_to_le32(tx_qgrp->txqs[j]->q_type); ++ vqv[k].queue_type = ++ cpu_to_le32(VIRTCHNL2_QUEUE_TYPE_TX); + vqv[k].queue_id = cpu_to_le32(tx_qgrp->txqs[j]->q_id); + + if (idpf_is_queue_model_split(vport->txq_model)) { +@@ -1879,14 +1885,15 @@ int idpf_send_map_unmap_queue_vector_msg(struct idpf_vport *vport, bool map) + num_rxq = rx_qgrp->singleq.num_rxq; + + for (j = 0; j < num_rxq; j++, k++) { +- struct idpf_queue *rxq; ++ struct idpf_rx_queue *rxq; + + if (idpf_is_queue_model_split(vport->rxq_model)) + rxq = &rx_qgrp->splitq.rxq_sets[j]->rxq; + else + rxq = rx_qgrp->singleq.rxqs[j]; + +- vqv[k].queue_type = cpu_to_le32(rxq->q_type); ++ vqv[k].queue_type = ++ cpu_to_le32(VIRTCHNL2_QUEUE_TYPE_RX); + vqv[k].queue_id = cpu_to_le32(rxq->q_id); + vqv[k].vector_id = cpu_to_le16(rxq->q_vector->v_idx); + vqv[k].itr_idx = cpu_to_le32(rxq->q_vector->rx_itr_idx); +@@ -1975,7 +1982,7 @@ int idpf_send_disable_queues_msg(struct idpf_vport *vport) + * queues virtchnl message is sent + */ + for (i = 0; i < vport->num_txq; i++) +- set_bit(__IDPF_Q_POLL_MODE, vport->txqs[i]->flags); ++ idpf_queue_set(POLL_MODE, vport->txqs[i]); + + /* schedule the napi to receive all the marker packets */ + local_bh_disable(); +@@ -3242,7 +3249,6 @@ static int __idpf_vport_queue_ids_init(struct idpf_vport *vport, + int num_qids, + u32 q_type) + { +- struct idpf_queue *q; + int i, j, k = 0; + + switch (q_type) { +@@ -3250,11 +3256,8 @@ static int __idpf_vport_queue_ids_init(struct idpf_vport *vport, + for (i = 0; i < vport->num_txq_grp; i++) { + struct idpf_txq_group *tx_qgrp = &vport->txq_grps[i]; + +- for (j = 0; j < tx_qgrp->num_txq && k < num_qids; j++, k++) { ++ for (j = 0; j < tx_qgrp->num_txq && k < num_qids; j++, k++) + tx_qgrp->txqs[j]->q_id = qids[k]; +- tx_qgrp->txqs[j]->q_type = +- VIRTCHNL2_QUEUE_TYPE_TX; +- } + } + break; + case VIRTCHNL2_QUEUE_TYPE_RX: +@@ -3268,12 +3271,13 @@ static int __idpf_vport_queue_ids_init(struct idpf_vport *vport, + num_rxq = rx_qgrp->singleq.num_rxq; + + for (j = 0; j < num_rxq && k < num_qids; j++, k++) { ++ struct idpf_rx_queue *q; ++ + if (idpf_is_queue_model_split(vport->rxq_model)) + q = &rx_qgrp->splitq.rxq_sets[j]->rxq; + else + q = rx_qgrp->singleq.rxqs[j]; + q->q_id = qids[k]; +- q->q_type = VIRTCHNL2_QUEUE_TYPE_RX; + } + } + break; +@@ -3282,8 +3286,6 @@ static int __idpf_vport_queue_ids_init(struct idpf_vport *vport, + struct idpf_txq_group *tx_qgrp = &vport->txq_grps[i]; + + tx_qgrp->complq->q_id = qids[k]; +- tx_qgrp->complq->q_type = +- VIRTCHNL2_QUEUE_TYPE_TX_COMPLETION; + } + break; + case VIRTCHNL2_QUEUE_TYPE_RX_BUFFER: +@@ -3292,9 +3294,10 @@ static int __idpf_vport_queue_ids_init(struct idpf_vport *vport, + u8 num_bufqs = vport->num_bufqs_per_qgrp; + + for (j = 0; j < num_bufqs && k < num_qids; j++, k++) { ++ struct idpf_buf_queue *q; ++ + q = &rx_qgrp->splitq.bufq_sets[j].bufq; + q->q_id = qids[k]; +- q->q_type = VIRTCHNL2_QUEUE_TYPE_RX_BUFFER; + } + } + break; +diff --git a/drivers/net/ethernet/realtek/r8169_phy_config.c b/drivers/net/ethernet/realtek/r8169_phy_config.c +index 1f74317beb8878..e1e5d9672ae44b 100644 +--- a/drivers/net/ethernet/realtek/r8169_phy_config.c ++++ b/drivers/net/ethernet/realtek/r8169_phy_config.c +@@ -1060,6 +1060,7 @@ static void rtl8125a_2_hw_phy_config(struct rtl8169_private *tp, + phy_modify_paged(phydev, 0xa86, 0x15, 0x0001, 0x0000); + rtl8168g_enable_gphy_10m(phydev); + ++ rtl8168g_disable_aldps(phydev); + rtl8125a_config_eee_phy(phydev); + } + +@@ -1099,6 +1100,7 @@ static void rtl8125b_hw_phy_config(struct rtl8169_private *tp, + phy_modify_paged(phydev, 0xbf8, 0x12, 0xe000, 0xa000); + + rtl8125_legacy_force_mode(phydev); ++ rtl8168g_disable_aldps(phydev); + rtl8125b_config_eee_phy(phydev); + } + +diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c +index 4d100283c30fb4..067357b2495cdc 100644 +--- a/drivers/net/ethernet/renesas/ravb_main.c ++++ b/drivers/net/ethernet/renesas/ravb_main.c +@@ -530,8 +530,16 @@ static void ravb_emac_init_gbeth(struct net_device *ndev) + + static void ravb_emac_init_rcar(struct net_device *ndev) + { +- /* Receive frame limit set register */ +- ravb_write(ndev, ndev->mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN, RFLR); ++ struct ravb_private *priv = netdev_priv(ndev); ++ ++ /* Set receive frame length ++ * ++ * The length set here describes the frame from the destination address ++ * up to and including the CRC data. However only the frame data, ++ * excluding the CRC, are transferred to memory. To allow for the ++ * largest frames add the CRC length to the maximum Rx descriptor size. ++ */ ++ ravb_write(ndev, priv->info->rx_max_frame_size + ETH_FCS_LEN, RFLR); + + /* EMAC Mode: PAUSE prohibition; Duplex; RX Checksum; TX; RX */ + ravb_write(ndev, ECMR_ZPF | ECMR_DM | +diff --git a/drivers/net/ethernet/seeq/ether3.c b/drivers/net/ethernet/seeq/ether3.c +index c672f92d65e976..9319a2675e7b65 100644 +--- a/drivers/net/ethernet/seeq/ether3.c ++++ b/drivers/net/ethernet/seeq/ether3.c +@@ -847,9 +847,11 @@ static void ether3_remove(struct expansion_card *ec) + { + struct net_device *dev = ecard_get_drvdata(ec); + ++ ether3_outw(priv(dev)->regs.config2 |= CFG2_CTRLO, REG_CONFIG2); + ecard_set_drvdata(ec, NULL); + + unregister_netdev(dev); ++ del_timer_sync(&priv(dev)->timer); + free_netdev(dev); + ecard_release_resources(ec); + } +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +index 9e40c28d453ab1..ee3604f58def52 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +@@ -35,6 +35,9 @@ static int loongson_default_data(struct plat_stmmacenet_data *plat) + /* Disable RX queues routing by default */ + plat->rx_queues_cfg[0].pkt_route = 0x0; + ++ plat->clk_ref_rate = 125000000; ++ plat->clk_ptp_rate = 125000000; ++ + /* Default to phy auto-detection */ + plat->phy_addr = -1; + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index 33e2bd5a351cad..3b1bb6aa5b8c8c 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -2025,7 +2025,7 @@ static int __alloc_dma_rx_desc_resources(struct stmmac_priv *priv, + rx_q->queue_index = queue; + rx_q->priv_data = priv; + +- pp_params.flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV; ++ pp_params.flags = PP_FLAG_DMA_MAP | (xdp_prog ? PP_FLAG_DMA_SYNC_DEV : 0); + pp_params.pool_size = dma_conf->dma_rx_size; + num_pages = DIV_ROUND_UP(dma_conf->dma_buf_sz, PAGE_SIZE); + pp_params.order = ilog2(num_pages); +diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +index 88d7bc2ea71326..f1d928644b8242 100644 +--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c ++++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +@@ -674,15 +674,15 @@ static int axienet_device_reset(struct net_device *ndev) + * + * Would either be called after a successful transmit operation, or after + * there was an error when setting up the chain. +- * Returns the number of descriptors handled. ++ * Returns the number of packets handled. + */ + static int axienet_free_tx_chain(struct axienet_local *lp, u32 first_bd, + int nr_bds, bool force, u32 *sizep, int budget) + { + struct axidma_bd *cur_p; + unsigned int status; ++ int i, packets = 0; + dma_addr_t phys; +- int i; + + for (i = 0; i < nr_bds; i++) { + cur_p = &lp->tx_bd_v[(first_bd + i) % lp->tx_bd_num]; +@@ -701,8 +701,10 @@ static int axienet_free_tx_chain(struct axienet_local *lp, u32 first_bd, + (cur_p->cntrl & XAXIDMA_BD_CTRL_LENGTH_MASK), + DMA_TO_DEVICE); + +- if (cur_p->skb && (status & XAXIDMA_BD_STS_COMPLETE_MASK)) ++ if (cur_p->skb && (status & XAXIDMA_BD_STS_COMPLETE_MASK)) { + napi_consume_skb(cur_p->skb, budget); ++ packets++; ++ } + + cur_p->app0 = 0; + cur_p->app1 = 0; +@@ -718,7 +720,13 @@ static int axienet_free_tx_chain(struct axienet_local *lp, u32 first_bd, + *sizep += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK; + } + +- return i; ++ if (!force) { ++ lp->tx_bd_ci += i; ++ if (lp->tx_bd_ci >= lp->tx_bd_num) ++ lp->tx_bd_ci %= lp->tx_bd_num; ++ } ++ ++ return packets; + } + + /** +@@ -891,13 +899,10 @@ static int axienet_tx_poll(struct napi_struct *napi, int budget) + u32 size = 0; + int packets; + +- packets = axienet_free_tx_chain(lp, lp->tx_bd_ci, budget, false, &size, budget); ++ packets = axienet_free_tx_chain(lp, lp->tx_bd_ci, lp->tx_bd_num, false, ++ &size, budget); + + if (packets) { +- lp->tx_bd_ci += packets; +- if (lp->tx_bd_ci >= lp->tx_bd_num) +- lp->tx_bd_ci %= lp->tx_bd_num; +- + u64_stats_update_begin(&lp->tx_stat_sync); + u64_stats_add(&lp->tx_packets, packets); + u64_stats_add(&lp->tx_bytes, size); +@@ -1222,9 +1227,10 @@ static irqreturn_t axienet_tx_irq(int irq, void *_ndev) + u32 cr = lp->tx_dma_cr; + + cr &= ~(XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK); +- axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr); +- +- napi_schedule(&lp->napi_tx); ++ if (napi_schedule_prep(&lp->napi_tx)) { ++ axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr); ++ __napi_schedule(&lp->napi_tx); ++ } + } + + return IRQ_HANDLED; +@@ -1266,9 +1272,10 @@ static irqreturn_t axienet_rx_irq(int irq, void *_ndev) + u32 cr = lp->rx_dma_cr; + + cr &= ~(XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK); +- axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr); +- +- napi_schedule(&lp->napi_rx); ++ if (napi_schedule_prep(&lp->napi_rx)) { ++ axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr); ++ __napi_schedule(&lp->napi_rx); ++ } + } + + return IRQ_HANDLED; +diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c +index 18eb5ba436df69..2506aa8c603ec0 100644 +--- a/drivers/net/usb/usbnet.c ++++ b/drivers/net/usb/usbnet.c +@@ -464,10 +464,15 @@ static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb, + void usbnet_defer_kevent (struct usbnet *dev, int work) + { + set_bit (work, &dev->flags); +- if (!schedule_work (&dev->kevent)) +- netdev_dbg(dev->net, "kevent %s may have been dropped\n", usbnet_event_names[work]); +- else +- netdev_dbg(dev->net, "kevent %s scheduled\n", usbnet_event_names[work]); ++ if (!usbnet_going_away(dev)) { ++ if (!schedule_work(&dev->kevent)) ++ netdev_dbg(dev->net, ++ "kevent %s may have been dropped\n", ++ usbnet_event_names[work]); ++ else ++ netdev_dbg(dev->net, ++ "kevent %s scheduled\n", usbnet_event_names[work]); ++ } + } + EXPORT_SYMBOL_GPL(usbnet_defer_kevent); + +@@ -535,7 +540,8 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) + tasklet_schedule (&dev->bh); + break; + case 0: +- __usbnet_queue_skb(&dev->rxq, skb, rx_start); ++ if (!usbnet_going_away(dev)) ++ __usbnet_queue_skb(&dev->rxq, skb, rx_start); + } + } else { + netif_dbg(dev, ifdown, dev->net, "rx: stopped\n"); +@@ -843,9 +849,18 @@ int usbnet_stop (struct net_device *net) + + /* deferred work (timer, softirq, task) must also stop */ + dev->flags = 0; +- del_timer_sync (&dev->delay); +- tasklet_kill (&dev->bh); ++ del_timer_sync(&dev->delay); ++ tasklet_kill(&dev->bh); + cancel_work_sync(&dev->kevent); ++ ++ /* We have cyclic dependencies. Those calls are needed ++ * to break a cycle. We cannot fall into the gaps because ++ * we have a flag ++ */ ++ tasklet_kill(&dev->bh); ++ del_timer_sync(&dev->delay); ++ cancel_work_sync(&dev->kevent); ++ + if (!pm) + usb_autopm_put_interface(dev->intf); + +@@ -1171,7 +1186,8 @@ usbnet_deferred_kevent (struct work_struct *work) + status); + } else { + clear_bit (EVENT_RX_HALT, &dev->flags); +- tasklet_schedule (&dev->bh); ++ if (!usbnet_going_away(dev)) ++ tasklet_schedule(&dev->bh); + } + } + +@@ -1196,7 +1212,8 @@ usbnet_deferred_kevent (struct work_struct *work) + usb_autopm_put_interface(dev->intf); + fail_lowmem: + if (resched) +- tasklet_schedule (&dev->bh); ++ if (!usbnet_going_away(dev)) ++ tasklet_schedule(&dev->bh); + } + } + +@@ -1559,6 +1576,7 @@ static void usbnet_bh (struct timer_list *t) + } else if (netif_running (dev->net) && + netif_device_present (dev->net) && + netif_carrier_ok(dev->net) && ++ !usbnet_going_away(dev) && + !timer_pending(&dev->delay) && + !test_bit(EVENT_RX_PAUSED, &dev->flags) && + !test_bit(EVENT_RX_HALT, &dev->flags)) { +@@ -1606,6 +1624,7 @@ void usbnet_disconnect (struct usb_interface *intf) + usb_set_intfdata(intf, NULL); + if (!dev) + return; ++ usbnet_mark_going_away(dev); + + xdev = interface_to_usbdev (intf); + +diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c +index 21bd0c127b05ab..0b1630bb173a5e 100644 +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -1439,6 +1439,11 @@ static struct sk_buff *receive_small(struct net_device *dev, + struct page *page = virt_to_head_page(buf); + struct sk_buff *skb; + ++ /* We passed the address of virtnet header to virtio-core, ++ * so truncate the padding. ++ */ ++ buf -= VIRTNET_RX_PAD + xdp_headroom; ++ + len -= vi->hdr_len; + u64_stats_add(&stats->bytes, len); + +@@ -2029,8 +2034,9 @@ static int add_recvbuf_small(struct virtnet_info *vi, struct receive_queue *rq, + if (unlikely(!buf)) + return -ENOMEM; + +- virtnet_rq_init_one_sg(rq, buf + VIRTNET_RX_PAD + xdp_headroom, +- vi->hdr_len + GOOD_PACKET_LEN); ++ buf += VIRTNET_RX_PAD + xdp_headroom; ++ ++ virtnet_rq_init_one_sg(rq, buf, vi->hdr_len + GOOD_PACKET_LEN); + + err = virtqueue_add_inbuf_ctx(rq->vq, rq->sg, 1, buf, ctx, gfp); + if (err < 0) { +diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h +index 141ba4487cb421..9d2d3a86abf172 100644 +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -396,6 +396,7 @@ struct ath11k_vif { + u8 bssid[ETH_ALEN]; + struct cfg80211_bitrate_mask bitrate_mask; + struct delayed_work connection_loss_work; ++ struct work_struct bcn_tx_work; + int num_legacy_stations; + int rtscts_prot_mode; + int txpower; +diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c +index eaa53bc39ab2c0..74719cb78888b1 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -6599,6 +6599,16 @@ static int ath11k_mac_vdev_delete(struct ath11k *ar, struct ath11k_vif *arvif) + return ret; + } + ++static void ath11k_mac_bcn_tx_work(struct work_struct *work) ++{ ++ struct ath11k_vif *arvif = container_of(work, struct ath11k_vif, ++ bcn_tx_work); ++ ++ mutex_lock(&arvif->ar->conf_mutex); ++ ath11k_mac_bcn_tx_event(arvif); ++ mutex_unlock(&arvif->ar->conf_mutex); ++} ++ + static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) + { +@@ -6637,6 +6647,7 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, + arvif->vif = vif; + + INIT_LIST_HEAD(&arvif->list); ++ INIT_WORK(&arvif->bcn_tx_work, ath11k_mac_bcn_tx_work); + INIT_DELAYED_WORK(&arvif->connection_loss_work, + ath11k_mac_vif_sta_connection_loss_work); + +@@ -6879,6 +6890,7 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw, + int i; + + cancel_delayed_work_sync(&arvif->connection_loss_work); ++ cancel_work_sync(&arvif->bcn_tx_work); + + mutex_lock(&ar->conf_mutex); + +diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c +index 6ff01c45f16591..f50a4c0d4b2bac 100644 +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -7404,7 +7404,9 @@ static void ath11k_bcn_tx_status_event(struct ath11k_base *ab, struct sk_buff *s + rcu_read_unlock(); + return; + } +- ath11k_mac_bcn_tx_event(arvif); ++ ++ queue_work(ab->workqueue, &arvif->bcn_tx_work); ++ + rcu_read_unlock(); + } + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 7037004ce97713..818ee74cf7a055 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -1948,9 +1948,8 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar, + * request, then use MAX_AMPDU_LEN_FACTOR as 16 to calculate max_ampdu + * length. + */ +- ampdu_factor = (he_cap->he_cap_elem.mac_cap_info[3] & +- IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK) >> +- IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK; ++ ampdu_factor = u8_get_bits(he_cap->he_cap_elem.mac_cap_info[3], ++ IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK); + + if (ampdu_factor) { + if (sta->deflink.vht_cap.vht_supported) +diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c +index ef775af25093c4..55230dd00d0c7b 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -1528,6 +1528,7 @@ int ath12k_wmi_pdev_bss_chan_info_request(struct ath12k *ar, + cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_BSS_CHAN_INFO_REQUEST, + sizeof(*cmd)); + cmd->req_type = cpu_to_le32(type); ++ cmd->pdev_id = cpu_to_le32(ar->pdev->pdev_id); + + ath12k_dbg(ar->ab, ATH12K_DBG_WMI, + "WMI bss chan info req type %d\n", type); +diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h +index 742fe0b36cf20a..e947d646353c38 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.h ++++ b/drivers/net/wireless/ath/ath12k/wmi.h +@@ -3104,6 +3104,7 @@ struct wmi_pdev_bss_chan_info_req_cmd { + __le32 tlv_header; + /* ref wmi_bss_chan_info_req_type */ + __le32 req_type; ++ __le32 pdev_id; + } __packed; + + struct wmi_ap_ps_peer_cmd { +@@ -4053,7 +4054,6 @@ struct wmi_vdev_stopped_event { + } __packed; + + struct wmi_pdev_bss_chan_info_event { +- __le32 pdev_id; + __le32 freq; /* Units in MHz */ + __le32 noise_floor; /* units are dBm */ + /* rx clear - how often the channel was unused */ +@@ -4071,6 +4071,7 @@ struct wmi_pdev_bss_chan_info_event { + /*rx_cycle cnt for my bss in 64bits format */ + __le32 rx_bss_cycle_count_low; + __le32 rx_bss_cycle_count_high; ++ __le32 pdev_id; + } __packed; + + #define WMI_VDEV_INSTALL_KEY_COMPL_STATUS_SUCCESS 0 +diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c +index d84e3ee7b5d902..bf3da631c69fda 100644 +--- a/drivers/net/wireless/ath/ath9k/debug.c ++++ b/drivers/net/wireless/ath/ath9k/debug.c +@@ -1380,8 +1380,6 @@ int ath9k_init_debug(struct ath_hw *ah) + + sc->debug.debugfs_phy = debugfs_create_dir("ath9k", + sc->hw->wiphy->debugfsdir); +- if (IS_ERR(sc->debug.debugfs_phy)) +- return -ENOMEM; + + #ifdef CONFIG_ATH_DEBUG + debugfs_create_file("debug", 0600, sc->debug.debugfs_phy, +diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +index f7c6d9bc931196..9437d69877cc56 100644 +--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c ++++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +@@ -486,8 +486,6 @@ int ath9k_htc_init_debug(struct ath_hw *ah) + + priv->debug.debugfs_phy = debugfs_create_dir(KBUILD_MODNAME, + priv->hw->wiphy->debugfsdir); +- if (IS_ERR(priv->debug.debugfs_phy)) +- return -ENOMEM; + + ath9k_cmn_spectral_init_debug(&priv->spec_priv, priv->debug.debugfs_phy); + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c +index 7ea2631b80692d..00794086cc7c97 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c +@@ -123,7 +123,7 @@ static s32 brcmf_btcoex_params_read(struct brcmf_if *ifp, u32 addr, u32 *data) + { + *data = addr; + +- return brcmf_fil_iovar_int_get(ifp, "btc_params", data); ++ return brcmf_fil_iovar_int_query(ifp, "btc_params", data); + } + + /** +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index 826b768196e289..ccc069ae5e9d8b 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -663,8 +663,8 @@ static int brcmf_cfg80211_request_sta_if(struct brcmf_if *ifp, u8 *macaddr) + /* interface_create version 3+ */ + /* get supported version from firmware side */ + iface_create_ver = 0; +- err = brcmf_fil_bsscfg_int_get(ifp, "interface_create", +- &iface_create_ver); ++ err = brcmf_fil_bsscfg_int_query(ifp, "interface_create", ++ &iface_create_ver); + if (err) { + brcmf_err("fail to get supported version, err=%d\n", err); + return -EOPNOTSUPP; +@@ -756,8 +756,8 @@ static int brcmf_cfg80211_request_ap_if(struct brcmf_if *ifp) + /* interface_create version 3+ */ + /* get supported version from firmware side */ + iface_create_ver = 0; +- err = brcmf_fil_bsscfg_int_get(ifp, "interface_create", +- &iface_create_ver); ++ err = brcmf_fil_bsscfg_int_query(ifp, "interface_create", ++ &iface_create_ver); + if (err) { + brcmf_err("fail to get supported version, err=%d\n", err); + return -EOPNOTSUPP; +@@ -2101,7 +2101,8 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) + if (!sme->crypto.n_akm_suites) + return 0; + +- err = brcmf_fil_bsscfg_int_get(netdev_priv(ndev), "wpa_auth", &val); ++ err = brcmf_fil_bsscfg_int_get(netdev_priv(ndev), ++ "wpa_auth", &val); + if (err) { + bphy_err(drvr, "could not get wpa_auth (%d)\n", err); + return err; +@@ -2680,7 +2681,7 @@ brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_vif *vif = wdev_to_vif(wdev); + struct brcmf_pub *drvr = cfg->pub; +- s32 qdbm = 0; ++ s32 qdbm; + s32 err; + + brcmf_dbg(TRACE, "Enter\n"); +@@ -3067,7 +3068,7 @@ brcmf_cfg80211_get_station_ibss(struct brcmf_if *ifp, + struct brcmf_scb_val_le scbval; + struct brcmf_pktcnt_le pktcnt; + s32 err; +- u32 rate = 0; ++ u32 rate; + u32 rssi; + + /* Get the current tx rate */ +@@ -7046,8 +7047,8 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg, + ch.bw = BRCMU_CHAN_BW_20; + cfg->d11inf.encchspec(&ch); + chaninfo = ch.chspec; +- err = brcmf_fil_bsscfg_int_get(ifp, "per_chan_info", +- &chaninfo); ++ err = brcmf_fil_bsscfg_int_query(ifp, "per_chan_info", ++ &chaninfo); + if (!err) { + if (chaninfo & WL_CHAN_RADAR) + channel->flags |= +@@ -7081,7 +7082,7 @@ static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg) + + /* verify support for bw_cap command */ + val = WLC_BAND_5G; +- err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &val); ++ err = brcmf_fil_iovar_int_query(ifp, "bw_cap", &val); + + if (!err) { + /* only set 2G bandwidth using bw_cap command */ +@@ -7157,11 +7158,11 @@ static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[]) + int err; + + band = WLC_BAND_2G; +- err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &band); ++ err = brcmf_fil_iovar_int_query(ifp, "bw_cap", &band); + if (!err) { + bw_cap[NL80211_BAND_2GHZ] = band; + band = WLC_BAND_5G; +- err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &band); ++ err = brcmf_fil_iovar_int_query(ifp, "bw_cap", &band); + if (!err) { + bw_cap[NL80211_BAND_5GHZ] = band; + return; +@@ -7170,7 +7171,6 @@ static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[]) + return; + } + brcmf_dbg(INFO, "fallback to mimo_bw_cap info\n"); +- mimo_bwcap = 0; + err = brcmf_fil_iovar_int_get(ifp, "mimo_bw_cap", &mimo_bwcap); + if (err) + /* assume 20MHz if firmware does not give a clue */ +@@ -7266,10 +7266,10 @@ static int brcmf_setup_wiphybands(struct brcmf_cfg80211_info *cfg) + struct brcmf_pub *drvr = cfg->pub; + struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0); + struct wiphy *wiphy = cfg_to_wiphy(cfg); +- u32 nmode = 0; ++ u32 nmode; + u32 vhtmode = 0; + u32 bw_cap[2] = { WLC_BW_20MHZ_BIT, WLC_BW_20MHZ_BIT }; +- u32 rxchain = 0; ++ u32 rxchain; + u32 nchain; + int err; + s32 i; +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +index bf91b1e1368f03..df53dd1d7e748a 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +@@ -691,7 +691,7 @@ static int brcmf_net_mon_open(struct net_device *ndev) + { + struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_pub *drvr = ifp->drvr; +- u32 monitor = 0; ++ u32 monitor; + int err; + + brcmf_dbg(TRACE, "Enter\n"); +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c +index f23310a77a5d11..0d9ae197fa1ec3 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c +@@ -184,7 +184,7 @@ static void brcmf_feat_wlc_version_overrides(struct brcmf_pub *drv) + static void brcmf_feat_iovar_int_get(struct brcmf_if *ifp, + enum brcmf_feat_id id, char *name) + { +- u32 data = 0; ++ u32 data; + int err; + + /* we need to know firmware error */ +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h +index a315a7fac6a06f..31e080e4da6697 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h +@@ -96,15 +96,22 @@ static inline + s32 brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data) + { + s32 err; +- __le32 data_le = cpu_to_le32(*data); + +- err = brcmf_fil_cmd_data_get(ifp, cmd, &data_le, sizeof(data_le)); ++ err = brcmf_fil_cmd_data_get(ifp, cmd, data, sizeof(*data)); + if (err == 0) +- *data = le32_to_cpu(data_le); ++ *data = le32_to_cpu(*(__le32 *)data); + brcmf_dbg(FIL, "ifidx=%d, cmd=%d, value=%d\n", ifp->ifidx, cmd, *data); + + return err; + } ++static inline ++s32 brcmf_fil_cmd_int_query(struct brcmf_if *ifp, u32 cmd, u32 *data) ++{ ++ __le32 *data_le = (__le32 *)data; ++ ++ *data_le = cpu_to_le32(*data); ++ return brcmf_fil_cmd_int_get(ifp, cmd, data); ++} + + s32 brcmf_fil_iovar_data_set(struct brcmf_if *ifp, const char *name, + const void *data, u32 len); +@@ -120,14 +127,21 @@ s32 brcmf_fil_iovar_int_set(struct brcmf_if *ifp, const char *name, u32 data) + static inline + s32 brcmf_fil_iovar_int_get(struct brcmf_if *ifp, const char *name, u32 *data) + { +- __le32 data_le = cpu_to_le32(*data); + s32 err; + +- err = brcmf_fil_iovar_data_get(ifp, name, &data_le, sizeof(data_le)); ++ err = brcmf_fil_iovar_data_get(ifp, name, data, sizeof(*data)); + if (err == 0) +- *data = le32_to_cpu(data_le); ++ *data = le32_to_cpu(*(__le32 *)data); + return err; + } ++static inline ++s32 brcmf_fil_iovar_int_query(struct brcmf_if *ifp, const char *name, u32 *data) ++{ ++ __le32 *data_le = (__le32 *)data; ++ ++ *data_le = cpu_to_le32(*data); ++ return brcmf_fil_iovar_int_get(ifp, name, data); ++} + + + s32 brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, const char *name, +@@ -145,15 +159,21 @@ s32 brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, const char *name, u32 data) + static inline + s32 brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, const char *name, u32 *data) + { +- __le32 data_le = cpu_to_le32(*data); + s32 err; + +- err = brcmf_fil_bsscfg_data_get(ifp, name, &data_le, +- sizeof(data_le)); ++ err = brcmf_fil_bsscfg_data_get(ifp, name, data, sizeof(*data)); + if (err == 0) +- *data = le32_to_cpu(data_le); ++ *data = le32_to_cpu(*(__le32 *)data); + return err; + } ++static inline ++s32 brcmf_fil_bsscfg_int_query(struct brcmf_if *ifp, const char *name, u32 *data) ++{ ++ __le32 *data_le = (__le32 *)data; ++ ++ *data_le = cpu_to_le32(*data); ++ return brcmf_fil_bsscfg_int_get(ifp, name, data); ++} + + s32 brcmf_fil_xtlv_data_set(struct brcmf_if *ifp, const char *name, u16 id, + void *data, u32 len); +diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c +index bc98b87cf2a131..02a95bf72740b1 100644 +--- a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c ++++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c +@@ -148,6 +148,17 @@ const struct iwl_cfg_trans_params iwl_bz_trans_cfg = { + .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US, + }; + ++const struct iwl_cfg_trans_params iwl_gl_trans_cfg = { ++ .device_family = IWL_DEVICE_FAMILY_BZ, ++ .base_params = &iwl_bz_base_params, ++ .mq_rx_supported = true, ++ .rf_id = true, ++ .gen2 = true, ++ .umac_prph_offset = 0x300000, ++ .xtal_latency = 12000, ++ .low_latency_xtal = true, ++}; ++ + const char iwl_bz_name[] = "Intel(R) TBD Bz device"; + const char iwl_fm_name[] = "Intel(R) Wi-Fi 7 BE201 320MHz"; + const char iwl_gl_name[] = "Intel(R) Wi-Fi 7 BE200 320MHz"; +diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h +index 732889f96ca27d..29a28b5c281142 100644 +--- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h ++++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h +@@ -503,6 +503,7 @@ extern const struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg; + extern const struct iwl_cfg_trans_params iwl_so_long_latency_imr_trans_cfg; + extern const struct iwl_cfg_trans_params iwl_ma_trans_cfg; + extern const struct iwl_cfg_trans_params iwl_bz_trans_cfg; ++extern const struct iwl_cfg_trans_params iwl_gl_trans_cfg; + extern const struct iwl_cfg_trans_params iwl_sc_trans_cfg; + extern const char iwl9162_name[]; + extern const char iwl9260_name[]; +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h +index 3cbeaddf435865..4ff643e9db5e36 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h +@@ -109,7 +109,7 @@ + #define IWL_MVM_FTM_INITIATOR_SECURE_LTF false + #define IWL_MVM_FTM_RESP_NDP_SUPPORT true + #define IWL_MVM_FTM_RESP_LMR_FEEDBACK_SUPPORT true +-#define IWL_MVM_FTM_NON_TB_MIN_TIME_BETWEEN_MSR 5 ++#define IWL_MVM_FTM_NON_TB_MIN_TIME_BETWEEN_MSR 7 + #define IWL_MVM_FTM_NON_TB_MAX_TIME_BETWEEN_MSR 1000 + #define IWL_MVM_D3_DEBUG false + #define IWL_MVM_USE_TWT true +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +index 9d681377cbab3f..f40d3e59d694a1 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +@@ -107,16 +107,14 @@ static void iwl_mvm_cleanup_roc(struct iwl_mvm *mvm) + iwl_mvm_flush_sta(mvm, mvm->aux_sta.sta_id, + mvm->aux_sta.tfd_queue_msk); + +- if (mvm->mld_api_is_used) { +- iwl_mvm_mld_rm_aux_sta(mvm); +- mutex_unlock(&mvm->mutex); +- return; +- } +- + /* In newer version of this command an aux station is added only + * in cases of dedicated tx queue and need to be removed in end +- * of use */ +- if (iwl_mvm_has_new_station_api(mvm->fw)) ++ * of use. For the even newer mld api, use the appropriate ++ * function. ++ */ ++ if (mvm->mld_api_is_used) ++ iwl_mvm_mld_rm_aux_sta(mvm); ++ else if (iwl_mvm_has_new_station_api(mvm->fw)) + iwl_mvm_rm_aux_sta(mvm); + } + +diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +index fed2754be68029..d93eec242204f2 100644 +--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c ++++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +@@ -500,10 +500,38 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct pci_device_id iwl_hw_card_ids[] = { + {IWL_PCI_DEVICE(0x7E40, PCI_ANY_ID, iwl_ma_trans_cfg)}, + + /* Bz devices */ +- {IWL_PCI_DEVICE(0x2727, PCI_ANY_ID, iwl_bz_trans_cfg)}, +- {IWL_PCI_DEVICE(0x272D, PCI_ANY_ID, iwl_bz_trans_cfg)}, +- {IWL_PCI_DEVICE(0x272b, PCI_ANY_ID, iwl_bz_trans_cfg)}, +- {IWL_PCI_DEVICE(0xA840, PCI_ANY_ID, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0x272b, PCI_ANY_ID, iwl_gl_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x0000, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x0090, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x0094, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x0098, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x009C, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x00C0, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x00C4, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x00E0, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x00E4, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x00E8, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x00EC, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x0100, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x0110, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x0114, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x0118, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x011C, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x0310, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x0314, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x0510, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x0A10, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x1671, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x1672, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x1771, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x1772, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x1791, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x1792, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x4090, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x40C4, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x40E0, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x4110, iwl_bz_trans_cfg)}, ++ {IWL_PCI_DEVICE(0xA840, 0x4314, iwl_bz_trans_cfg)}, + {IWL_PCI_DEVICE(0x7740, PCI_ANY_ID, iwl_bz_trans_cfg)}, + {IWL_PCI_DEVICE(0x4D40, PCI_ANY_ID, iwl_bz_trans_cfg)}, + +diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c +index e8ba2e4e8484a8..b5dbcf925f9227 100644 +--- a/drivers/net/wireless/mediatek/mt76/mac80211.c ++++ b/drivers/net/wireless/mediatek/mt76/mac80211.c +@@ -1524,7 +1524,7 @@ EXPORT_SYMBOL_GPL(mt76_wcid_init); + + void mt76_wcid_cleanup(struct mt76_dev *dev, struct mt76_wcid *wcid) + { +- struct mt76_phy *phy = dev->phys[wcid->phy_idx]; ++ struct mt76_phy *phy = mt76_dev_phy(dev, wcid->phy_idx); + struct ieee80211_hw *hw; + struct sk_buff_head list; + struct sk_buff *skb; +diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c +index 14304b06371588..e238161dfaa971 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c +@@ -29,7 +29,7 @@ mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb) + struct ieee80211_sta *sta; + struct mt7603_sta *msta; + struct mt76_wcid *wcid; +- u8 tid = 0, hwq = 0; ++ u8 qid, tid = 0, hwq = 0; + void *priv; + int idx; + u32 val; +@@ -57,7 +57,7 @@ mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb) + if (ieee80211_is_data_qos(hdr->frame_control)) { + tid = *ieee80211_get_qos_ctl(hdr) & + IEEE80211_QOS_CTL_TAG1D_MASK; +- u8 qid = tid_to_ac[tid]; ++ qid = tid_to_ac[tid]; + hwq = wmm_queue_map[qid]; + skb_set_queue_mapping(skb, qid); + } else if (ieee80211_is_data(hdr->frame_control)) { +diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c +index f7722f67db576f..0b9ebdcda221e4 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c +@@ -56,6 +56,9 @@ int mt7615_thermal_init(struct mt7615_dev *dev) + + name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7615_%s", + wiphy_name(wiphy)); ++ if (!name) ++ return -ENOMEM; ++ + hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, dev, + mt7615_hwmon_groups); + return PTR_ERR_OR_ZERO(hwmon); +diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h +index 353e6606984093..ef003d1620a5b7 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h ++++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h +@@ -28,8 +28,6 @@ enum { + #define MT_RXD0_MESH BIT(18) + #define MT_RXD0_MHCP BIT(19) + #define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16) +-#define MT_RXD0_NORMAL_IP_SUM BIT(23) +-#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24) + + #define MT_RXD0_SW_PKT_TYPE_MASK GENMASK(31, 16) + #define MT_RXD0_SW_PKT_TYPE_MAP 0x380F +@@ -80,6 +78,8 @@ enum { + #define MT_RXD3_NORMAL_BEACON_UC BIT(21) + #define MT_RXD3_NORMAL_CO_ANT BIT(22) + #define MT_RXD3_NORMAL_FCS_ERR BIT(24) ++#define MT_RXD3_NORMAL_IP_SUM BIT(26) ++#define MT_RXD3_NORMAL_UDP_TCP_SUM BIT(27) + #define MT_RXD3_NORMAL_VLAN2ETH BIT(31) + + /* RXD DW4 */ +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c +index a978f434dc5e64..7bc3b4cd359255 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c +@@ -194,6 +194,8 @@ static int mt7915_thermal_init(struct mt7915_phy *phy) + + name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7915_%s", + wiphy_name(wiphy)); ++ if (!name) ++ return -ENOMEM; + + cdev = thermal_cooling_device_register(name, phy, &mt7915_thermal_ops); + if (!IS_ERR(cdev)) { +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c +index 2624edbb59a1a5..eea41b29f09675 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c +@@ -564,8 +564,7 @@ static void mt7915_configure_filter(struct ieee80211_hw *hw, + + MT76_FILTER(CONTROL, MT_WF_RFCR_DROP_CTS | + MT_WF_RFCR_DROP_RTS | +- MT_WF_RFCR_DROP_CTL_RSV | +- MT_WF_RFCR_DROP_NDPA); ++ MT_WF_RFCR_DROP_CTL_RSV); + + *total_flags = flags; + rxfilter = phy->rxfilter; +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c +index ef0c721d26e332..d1d64fa7d35d02 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c +@@ -52,6 +52,8 @@ static int mt7921_thermal_init(struct mt792x_phy *phy) + + name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7921_%s", + wiphy_name(wiphy)); ++ if (!name) ++ return -ENOMEM; + + hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy, + mt7921_hwmon_groups); +@@ -83,7 +85,7 @@ mt7921_regd_channel_update(struct wiphy *wiphy, struct mt792x_dev *dev) + } + + /* UNII-4 */ +- if (IS_UNII_INVALID(0, 5850, 5925)) ++ if (IS_UNII_INVALID(0, 5845, 5925)) + ch->flags |= IEEE80211_CHAN_DISABLED; + } + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c +index c2460ef4993db6..e9d2d0f22a5863 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c +@@ -350,7 +350,7 @@ mt7925_mac_fill_rx_rate(struct mt792x_dev *dev, + static int + mt7925_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb) + { +- u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM; ++ u32 csum_mask = MT_RXD3_NORMAL_IP_SUM | MT_RXD3_NORMAL_UDP_TCP_SUM; + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + bool hdr_trans, unicast, insert_ccmp_hdr = false; + u8 chfreq, qos_ctl = 0, remove_pad, amsdu_info; +@@ -360,7 +360,6 @@ mt7925_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb) + struct mt792x_phy *phy = &dev->phy; + struct ieee80211_supported_band *sband; + u32 csum_status = *(u32 *)skb->cb; +- u32 rxd0 = le32_to_cpu(rxd[0]); + u32 rxd1 = le32_to_cpu(rxd[1]); + u32 rxd2 = le32_to_cpu(rxd[2]); + u32 rxd3 = le32_to_cpu(rxd[3]); +@@ -418,7 +417,7 @@ mt7925_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb) + if (!sband->channels) + return -EINVAL; + +- if (mt76_is_mmio(&dev->mt76) && (rxd0 & csum_mask) == csum_mask && ++ if (mt76_is_mmio(&dev->mt76) && (rxd3 & csum_mask) == csum_mask && + !(csum_status & (BIT(0) | BIT(2) | BIT(3)))) + skb->ip_summed = CHECKSUM_UNNECESSARY; + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +index 652a9accc43cc3..7ec6bb5bc2767f 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +@@ -613,6 +613,9 @@ static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name) + for (offset = 0; offset < len; offset += le32_to_cpu(clc->len)) { + clc = (const struct mt7925_clc *)(clc_base + offset); + ++ if (clc->idx > ARRAY_SIZE(phy->clc)) ++ break; ++ + /* do not init buf again if chip reset triggered */ + if (phy->clc[clc->idx]) + continue; +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c +index 283df84f1b4335..a98dcb40490bf8 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c +@@ -1011,8 +1011,6 @@ mt7996_set_stream_he_txbf_caps(struct mt7996_phy *phy, + return; + + elem->phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER; +- if (vif == NL80211_IFTYPE_AP) +- elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER; + + c = FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK, + sts - 1) | +@@ -1020,6 +1018,11 @@ mt7996_set_stream_he_txbf_caps(struct mt7996_phy *phy, + sts - 1); + elem->phy_cap_info[5] |= c; + ++ if (vif != NL80211_IFTYPE_AP) ++ return; ++ ++ elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER; ++ + c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB | + IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB; + elem->phy_cap_info[6] |= c; +@@ -1179,7 +1182,6 @@ mt7996_init_eht_caps(struct mt7996_phy *phy, enum nl80211_band band, + IEEE80211_EHT_MAC_CAP0_OM_CONTROL; + + eht_cap_elem->phy_cap_info[0] = +- IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ | + IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI | + IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER | + IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE; +@@ -1193,30 +1195,36 @@ mt7996_init_eht_caps(struct mt7996_phy *phy, enum nl80211_band band, + u8_encode_bits(u8_get_bits(val, GENMASK(2, 1)), + IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK) | + u8_encode_bits(val, +- IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK) | +- u8_encode_bits(val, +- IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK); ++ IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK); + + eht_cap_elem->phy_cap_info[2] = + u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_80MHZ_MASK) | +- u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_160MHZ_MASK) | +- u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK); ++ u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_160MHZ_MASK); ++ ++ if (band == NL80211_BAND_6GHZ) { ++ eht_cap_elem->phy_cap_info[0] |= ++ IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ; ++ ++ eht_cap_elem->phy_cap_info[1] |= ++ u8_encode_bits(val, ++ IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK); ++ ++ eht_cap_elem->phy_cap_info[2] |= ++ u8_encode_bits(sts - 1, ++ IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK); ++ } + + eht_cap_elem->phy_cap_info[3] = + IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK | + IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK | + IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK | +- IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK | +- IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK | +- IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK | +- IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK; ++ IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK; + + eht_cap_elem->phy_cap_info[4] = + u8_encode_bits(min_t(int, sts - 1, 2), + IEEE80211_EHT_PHY_CAP4_MAX_NC_MASK); + + eht_cap_elem->phy_cap_info[5] = +- IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK | + u8_encode_bits(IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_16US, + IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK) | + u8_encode_bits(u8_get_bits(0x11, GENMASK(1, 0)), +@@ -1230,14 +1238,6 @@ mt7996_init_eht_caps(struct mt7996_phy *phy, enum nl80211_band band, + IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK) | + u8_encode_bits(val, IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK); + +- eht_cap_elem->phy_cap_info[7] = +- IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ | +- IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ | +- IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ | +- IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ | +- IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ | +- IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ; +- + val = u8_encode_bits(nss, IEEE80211_EHT_MCS_NSS_RX) | + u8_encode_bits(nss, IEEE80211_EHT_MCS_NSS_TX); + #define SET_EHT_MAX_NSS(_bw, _val) do { \ +@@ -1248,8 +1248,29 @@ mt7996_init_eht_caps(struct mt7996_phy *phy, enum nl80211_band band, + + SET_EHT_MAX_NSS(80, val); + SET_EHT_MAX_NSS(160, val); +- SET_EHT_MAX_NSS(320, val); ++ if (band == NL80211_BAND_6GHZ) ++ SET_EHT_MAX_NSS(320, val); + #undef SET_EHT_MAX_NSS ++ ++ if (iftype != NL80211_IFTYPE_AP) ++ return; ++ ++ eht_cap_elem->phy_cap_info[3] |= ++ IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK | ++ IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK; ++ ++ eht_cap_elem->phy_cap_info[7] = ++ IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ | ++ IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ | ++ IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ | ++ IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ; ++ ++ if (band != NL80211_BAND_6GHZ) ++ return; ++ ++ eht_cap_elem->phy_cap_info[7] |= ++ IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ | ++ IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ; + } + + static void +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +index bc7111a71f98ca..fd5fe96c32e3d1 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +@@ -435,7 +435,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q, + u32 rxd2 = le32_to_cpu(rxd[2]); + u32 rxd3 = le32_to_cpu(rxd[3]); + u32 rxd4 = le32_to_cpu(rxd[4]); +- u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM; ++ u32 csum_mask = MT_RXD3_NORMAL_IP_SUM | MT_RXD3_NORMAL_UDP_TCP_SUM; + u32 csum_status = *(u32 *)skb->cb; + u32 mesh_mask = MT_RXD0_MESH | MT_RXD0_MHCP; + bool is_mesh = (rxd0 & mesh_mask) == mesh_mask; +@@ -497,7 +497,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q, + if (!sband->channels) + return -EINVAL; + +- if ((rxd0 & csum_mask) == csum_mask && ++ if ((rxd3 & csum_mask) == csum_mask && + !(csum_status & (BIT(0) | BIT(2) | BIT(3)))) + skb->ip_summed = CHECKSUM_UNNECESSARY; + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c +index 7c97140d8255a7..2b094b33ba31ac 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c +@@ -206,7 +206,7 @@ static int mt7996_add_interface(struct ieee80211_hw *hw, + mvif->mt76.omac_idx = idx; + mvif->phy = phy; + mvif->mt76.band_idx = band_idx; +- mvif->mt76.wmm_idx = vif->type != NL80211_IFTYPE_AP; ++ mvif->mt76.wmm_idx = vif->type == NL80211_IFTYPE_AP ? 0 : 3; + + ret = mt7996_mcu_add_dev_info(phy, vif, true); + if (ret) +@@ -307,6 +307,10 @@ int mt7996_set_channel(struct mt7996_phy *phy) + if (ret) + goto out; + ++ ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_RX_PATH); ++ if (ret) ++ goto out; ++ + ret = mt7996_dfs_init_radar_detector(phy); + mt7996_mac_cca_stats_reset(phy); + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +index 2c857867780095..36ab59885cf2b6 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +@@ -735,7 +735,7 @@ void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb) + static struct tlv * + mt7996_mcu_add_uni_tlv(struct sk_buff *skb, u16 tag, u16 len) + { +- struct tlv *ptlv = skb_put(skb, len); ++ struct tlv *ptlv = skb_put_zero(skb, len); + + ptlv->tag = cpu_to_le16(tag); + ptlv->len = cpu_to_le16(len); +@@ -822,7 +822,7 @@ mt7996_mcu_bss_mbssid_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct bss_info_uni_mbssid *mbssid; + struct tlv *tlv; + +- if (!vif->bss_conf.bssid_indicator) ++ if (!vif->bss_conf.bssid_indicator && enable) + return; + + tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_11V_MBSSID, sizeof(*mbssid)); +@@ -1429,10 +1429,10 @@ mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif, + + if (bfee) + return vif->bss_conf.eht_su_beamformee && +- EHT_PHY(CAP0_SU_BEAMFORMEE, pe->phy_cap_info[0]); ++ EHT_PHY(CAP0_SU_BEAMFORMER, pe->phy_cap_info[0]); + else + return vif->bss_conf.eht_su_beamformer && +- EHT_PHY(CAP0_SU_BEAMFORMER, pe->phy_cap_info[0]); ++ EHT_PHY(CAP0_SU_BEAMFORMEE, pe->phy_cap_info[0]); + } + + if (sta->deflink.he_cap.has_he) { +@@ -1544,6 +1544,9 @@ mt7996_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif, + u8 nss_mcs = mt7996_mcu_get_sta_nss(mcs_map); + u8 snd_dim, sts; + ++ if (!vc) ++ return; ++ + bf->tx_mode = MT_PHY_TYPE_HE_SU; + + mt7996_mcu_sta_sounding_rate(bf); +@@ -1653,7 +1656,7 @@ mt7996_mcu_sta_bfer_tlv(struct mt7996_dev *dev, struct sk_buff *skb, + { + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt7996_phy *phy = mvif->phy; +- int tx_ant = hweight8(phy->mt76->chainmask) - 1; ++ int tx_ant = hweight16(phy->mt76->chainmask) - 1; + struct sta_rec_bf *bf; + struct tlv *tlv; + static const u8 matrix[4][4] = { +diff --git a/drivers/net/wireless/microchip/wilc1000/hif.c b/drivers/net/wireless/microchip/wilc1000/hif.c +index 7719e4f3e2a23a..2ee8c8e365f89f 100644 +--- a/drivers/net/wireless/microchip/wilc1000/hif.c ++++ b/drivers/net/wireless/microchip/wilc1000/hif.c +@@ -384,6 +384,7 @@ wilc_parse_join_bss_param(struct cfg80211_bss *bss, + struct wilc_join_bss_param *param; + u8 rates_len = 0; + int ies_len; ++ u64 ies_tsf; + int ret; + + param = kzalloc(sizeof(*param), GFP_KERNEL); +@@ -399,6 +400,7 @@ wilc_parse_join_bss_param(struct cfg80211_bss *bss, + return NULL; + } + ies_len = ies->len; ++ ies_tsf = ies->tsf; + rcu_read_unlock(); + + param->beacon_period = cpu_to_le16(bss->beacon_interval); +@@ -454,7 +456,7 @@ wilc_parse_join_bss_param(struct cfg80211_bss *bss, + IEEE80211_P2P_ATTR_ABSENCE_NOTICE, + (u8 *)&noa_attr, sizeof(noa_attr)); + if (ret > 0) { +- param->tsf_lo = cpu_to_le32(ies->tsf); ++ param->tsf_lo = cpu_to_le32(ies_tsf); + param->noa_enabled = 1; + param->idx = noa_attr.index; + if (noa_attr.oppps_ctwindow & IEEE80211_P2P_OPPPS_ENABLE_BIT) { +diff --git a/drivers/net/wireless/realtek/rtw88/coex.c b/drivers/net/wireless/realtek/rtw88/coex.c +index de3332eb7a227a..a99776af56c27f 100644 +--- a/drivers/net/wireless/realtek/rtw88/coex.c ++++ b/drivers/net/wireless/realtek/rtw88/coex.c +@@ -2194,7 +2194,6 @@ static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev) + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_efuse *efuse = &rtwdev->efuse; + u8 table_case, tdma_case; +- bool wl_cpt_test = false, bt_cpt_test = false; + + rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); + +@@ -2202,29 +2201,16 @@ static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev) + rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + if (efuse->share_ant) { + /* Shared-Ant */ +- if (wl_cpt_test) { +- if (coex_stat->wl_gl_busy) { +- table_case = 20; +- tdma_case = 17; +- } else { +- table_case = 10; +- tdma_case = 15; +- } +- } else if (bt_cpt_test) { +- table_case = 26; +- tdma_case = 26; +- } else { +- if (coex_stat->wl_gl_busy && +- coex_stat->wl_noisy_level == 0) +- table_case = 14; +- else +- table_case = 10; ++ if (coex_stat->wl_gl_busy && ++ coex_stat->wl_noisy_level == 0) ++ table_case = 14; ++ else ++ table_case = 10; + +- if (coex_stat->wl_gl_busy) +- tdma_case = 15; +- else +- tdma_case = 20; +- } ++ if (coex_stat->wl_gl_busy) ++ tdma_case = 15; ++ else ++ tdma_case = 20; + } else { + /* Non-Shared-Ant */ + table_case = 112; +@@ -2235,11 +2221,7 @@ static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev) + tdma_case = 120; + } + +- if (wl_cpt_test) +- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[1]); +- else +- rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); +- ++ rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); + rtw_coex_table(rtwdev, false, table_case); + rtw_coex_tdma(rtwdev, false, tdma_case); + } +diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c +index ab7d414d0ba679..b9b0114e253b43 100644 +--- a/drivers/net/wireless/realtek/rtw88/fw.c ++++ b/drivers/net/wireless/realtek/rtw88/fw.c +@@ -1468,10 +1468,12 @@ int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr, + val |= BIT_ENSWBCN >> 8; + rtw_write8(rtwdev, REG_CR + 1, val); + +- val = rtw_read8(rtwdev, REG_FWHW_TXQ_CTRL + 2); +- bckp[1] = val; +- val &= ~(BIT_EN_BCNQ_DL >> 16); +- rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 2, val); ++ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_PCIE) { ++ val = rtw_read8(rtwdev, REG_FWHW_TXQ_CTRL + 2); ++ bckp[1] = val; ++ val &= ~(BIT_EN_BCNQ_DL >> 16); ++ rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 2, val); ++ } + + ret = rtw_hci_write_data_rsvd_page(rtwdev, buf, size); + if (ret) { +@@ -1496,7 +1498,8 @@ int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr, + rsvd_pg_head = rtwdev->fifo.rsvd_boundary; + rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2, + rsvd_pg_head | BIT_BCN_VALID_V1); +- rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 2, bckp[1]); ++ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_PCIE) ++ rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 2, bckp[1]); + rtw_write8(rtwdev, REG_CR + 1, bckp[0]); + + return ret; +diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c +index 7ab7a988b123f1..33a7577557a568 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.c ++++ b/drivers/net/wireless/realtek/rtw88/main.c +@@ -1313,20 +1313,21 @@ static int rtw_wait_firmware_completion(struct rtw_dev *rtwdev) + { + const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_fw_state *fw; ++ int ret = 0; + + fw = &rtwdev->fw; + wait_for_completion(&fw->completion); + if (!fw->firmware) +- return -EINVAL; ++ ret = -EINVAL; + + if (chip->wow_fw_name) { + fw = &rtwdev->wow_fw; + wait_for_completion(&fw->completion); + if (!fw->firmware) +- return -EINVAL; ++ ret = -EINVAL; + } + +- return 0; ++ return ret; + } + + static enum rtw_lps_deep_mode rtw_update_lps_deep_mode(struct rtw_dev *rtwdev, +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821cu.c b/drivers/net/wireless/realtek/rtw88/rtw8821cu.c +index e2c7d9f876836a..a019f4085e7389 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8821cu.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821cu.c +@@ -31,8 +31,6 @@ static const struct usb_device_id rtw_8821cu_id_table[] = { + .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, + { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82b, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, +- { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82c, 0xff, 0xff, 0xff), +- .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x331d, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* D-Link */ + { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xc811, 0xff, 0xff, 0xff), +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +index 62376d1cca22fc..732d787652208b 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +@@ -2611,12 +2611,14 @@ static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status, + else + rxsc = GET_PHY_STAT_P1_HT_RXSC(phy_status); + +- if (rxsc >= 9 && rxsc <= 12) ++ if (rxsc == 0) ++ bw = rtwdev->hal.current_band_width; ++ else if (rxsc >= 1 && rxsc <= 8) ++ bw = RTW_CHANNEL_WIDTH_20; ++ else if (rxsc >= 9 && rxsc <= 12) + bw = RTW_CHANNEL_WIDTH_40; +- else if (rxsc >= 13) +- bw = RTW_CHANNEL_WIDTH_80; + else +- bw = RTW_CHANNEL_WIDTH_20; ++ bw = RTW_CHANNEL_WIDTH_80; + + channel = GET_PHY_STAT_P1_CHANNEL(phy_status); + rtw_set_rx_freq_band(pkt_stat, channel); +diff --git a/drivers/net/wireless/realtek/rtw88/rx.h b/drivers/net/wireless/realtek/rtw88/rx.h +index d3668c4efc24d5..8a072dd3d73ce4 100644 +--- a/drivers/net/wireless/realtek/rtw88/rx.h ++++ b/drivers/net/wireless/realtek/rtw88/rx.h +@@ -41,7 +41,7 @@ enum rtw_rx_desc_enc { + #define GET_RX_DESC_TSFL(rxdesc) \ + le32_get_bits(*((__le32 *)(rxdesc) + 0x05), GENMASK(31, 0)) + #define GET_RX_DESC_BW(rxdesc) \ +- (le32_get_bits(*((__le32 *)(rxdesc) + 0x04), GENMASK(31, 24))) ++ (le32_get_bits(*((__le32 *)(rxdesc) + 0x04), GENMASK(5, 4))) + + void rtw_rx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, + struct sk_buff *skb); +diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h +index a580cb71923379..755a55c8bc20bf 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac.h ++++ b/drivers/net/wireless/realtek/rtw89/mac.h +@@ -421,7 +421,6 @@ enum rtw89_mac_c2h_mrc_func { + + enum rtw89_mac_c2h_wow_func { + RTW89_MAC_C2H_FUNC_AOAC_REPORT, +- RTW89_MAC_C2H_FUNC_READ_WOW_CAM, + + NUM_OF_RTW89_MAC_C2H_FUNC_WOW, + }; +diff --git a/drivers/ntb/hw/intel/ntb_hw_gen1.c b/drivers/ntb/hw/intel/ntb_hw_gen1.c +index 9ab836d0d4f12d..079b8cd7978573 100644 +--- a/drivers/ntb/hw/intel/ntb_hw_gen1.c ++++ b/drivers/ntb/hw/intel/ntb_hw_gen1.c +@@ -778,7 +778,7 @@ static void ndev_init_debugfs(struct intel_ntb_dev *ndev) + ndev->debugfs_dir = + debugfs_create_dir(pci_name(ndev->ntb.pdev), + debugfs_dir); +- if (!ndev->debugfs_dir) ++ if (IS_ERR(ndev->debugfs_dir)) + ndev->debugfs_info = NULL; + else + ndev->debugfs_info = +diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c +index f9e7847a378e77..c84fadfc63c52c 100644 +--- a/drivers/ntb/ntb_transport.c ++++ b/drivers/ntb/ntb_transport.c +@@ -807,16 +807,29 @@ static void ntb_free_mw(struct ntb_transport_ctx *nt, int num_mw) + } + + static int ntb_alloc_mw_buffer(struct ntb_transport_mw *mw, +- struct device *dma_dev, size_t align) ++ struct device *ntb_dev, size_t align) + { + dma_addr_t dma_addr; + void *alloc_addr, *virt_addr; + int rc; + +- alloc_addr = dma_alloc_coherent(dma_dev, mw->alloc_size, +- &dma_addr, GFP_KERNEL); ++ /* ++ * The buffer here is allocated against the NTB device. The reason to ++ * use dma_alloc_*() call is to allocate a large IOVA contiguous buffer ++ * backing the NTB BAR for the remote host to write to. During receive ++ * processing, the data is being copied out of the receive buffer to ++ * the kernel skbuff. When a DMA device is being used, dma_map_page() ++ * is called on the kvaddr of the receive buffer (from dma_alloc_*()) ++ * and remapped against the DMA device. It appears to be a double ++ * DMA mapping of buffers, but first is mapped to the NTB device and ++ * second is to the DMA device. DMA_ATTR_FORCE_CONTIGUOUS is necessary ++ * in order for the later dma_map_page() to not fail. ++ */ ++ alloc_addr = dma_alloc_attrs(ntb_dev, mw->alloc_size, ++ &dma_addr, GFP_KERNEL, ++ DMA_ATTR_FORCE_CONTIGUOUS); + if (!alloc_addr) { +- dev_err(dma_dev, "Unable to alloc MW buff of size %zu\n", ++ dev_err(ntb_dev, "Unable to alloc MW buff of size %zu\n", + mw->alloc_size); + return -ENOMEM; + } +@@ -845,7 +858,7 @@ static int ntb_alloc_mw_buffer(struct ntb_transport_mw *mw, + return 0; + + err: +- dma_free_coherent(dma_dev, mw->alloc_size, alloc_addr, dma_addr); ++ dma_free_coherent(ntb_dev, mw->alloc_size, alloc_addr, dma_addr); + + return rc; + } +diff --git a/drivers/ntb/test/ntb_perf.c b/drivers/ntb/test/ntb_perf.c +index 553f1f46bc664f..72bc1d017a46ee 100644 +--- a/drivers/ntb/test/ntb_perf.c ++++ b/drivers/ntb/test/ntb_perf.c +@@ -1227,7 +1227,7 @@ static ssize_t perf_dbgfs_read_info(struct file *filep, char __user *ubuf, + "\tOut buffer addr 0x%pK\n", peer->outbuf); + + pos += scnprintf(buf + pos, buf_size - pos, +- "\tOut buff phys addr %pa[p]\n", &peer->out_phys_addr); ++ "\tOut buff phys addr %pap\n", &peer->out_phys_addr); + + pos += scnprintf(buf + pos, buf_size - pos, + "\tOut buffer size %pa\n", &peer->outbuf_size); +diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c +index d6d558f94d6bb2..35d9f3cc2efabf 100644 +--- a/drivers/nvdimm/namespace_devs.c ++++ b/drivers/nvdimm/namespace_devs.c +@@ -1937,12 +1937,16 @@ static int cmp_dpa(const void *a, const void *b) + static struct device **scan_labels(struct nd_region *nd_region) + { + int i, count = 0; +- struct device *dev, **devs = NULL; ++ struct device *dev, **devs; + struct nd_label_ent *label_ent, *e; + struct nd_mapping *nd_mapping = &nd_region->mapping[0]; + struct nvdimm_drvdata *ndd = to_ndd(nd_mapping); + resource_size_t map_end = nd_mapping->start + nd_mapping->size - 1; + ++ devs = kcalloc(2, sizeof(dev), GFP_KERNEL); ++ if (!devs) ++ return NULL; ++ + /* "safe" because create_namespace_pmem() might list_move() label_ent */ + list_for_each_entry_safe(label_ent, e, &nd_mapping->labels, list) { + struct nd_namespace_label *nd_label = label_ent->label; +@@ -1961,12 +1965,14 @@ static struct device **scan_labels(struct nd_region *nd_region) + goto err; + if (i < count) + continue; +- __devs = kcalloc(count + 2, sizeof(dev), GFP_KERNEL); +- if (!__devs) +- goto err; +- memcpy(__devs, devs, sizeof(dev) * count); +- kfree(devs); +- devs = __devs; ++ if (count) { ++ __devs = kcalloc(count + 2, sizeof(dev), GFP_KERNEL); ++ if (!__devs) ++ goto err; ++ memcpy(__devs, devs, sizeof(dev) * count); ++ kfree(devs); ++ devs = __devs; ++ } + + dev = create_namespace_pmem(nd_region, nd_mapping, nd_label); + if (IS_ERR(dev)) { +@@ -1993,11 +1999,6 @@ static struct device **scan_labels(struct nd_region *nd_region) + + /* Publish a zero-sized namespace for userspace to configure. */ + nd_mapping_free_labels(nd_mapping); +- +- devs = kcalloc(2, sizeof(dev), GFP_KERNEL); +- if (!devs) +- goto err; +- + nspm = kzalloc(sizeof(*nspm), GFP_KERNEL); + if (!nspm) + goto err; +@@ -2036,11 +2037,10 @@ static struct device **scan_labels(struct nd_region *nd_region) + return devs; + + err: +- if (devs) { +- for (i = 0; devs[i]; i++) +- namespace_pmem_release(devs[i]); +- kfree(devs); +- } ++ for (i = 0; devs[i]; i++) ++ namespace_pmem_release(devs[i]); ++ kfree(devs); ++ + return NULL; + } + +diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c +index 03a6868f4dbc18..a47d35102b7ce7 100644 +--- a/drivers/nvme/host/multipath.c ++++ b/drivers/nvme/host/multipath.c +@@ -587,7 +587,7 @@ static void nvme_mpath_set_live(struct nvme_ns *ns) + rc = device_add_disk(&head->subsys->dev, head->disk, + nvme_ns_attr_groups); + if (rc) { +- clear_bit(NVME_NSHEAD_DISK_LIVE, &ns->flags); ++ clear_bit(NVME_NSHEAD_DISK_LIVE, &head->flags); + return; + } + nvme_add_ns_head_cdev(head); +diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c +index d2d17d37d3e0b5..4c67fa78db2677 100644 +--- a/drivers/pci/controller/dwc/pci-dra7xx.c ++++ b/drivers/pci/controller/dwc/pci-dra7xx.c +@@ -850,14 +850,21 @@ static int dra7xx_pcie_probe(struct platform_device *pdev) + dra7xx->mode = mode; + + ret = devm_request_threaded_irq(dev, irq, NULL, dra7xx_pcie_irq_handler, +- IRQF_SHARED, "dra7xx-pcie-main", dra7xx); ++ IRQF_SHARED | IRQF_ONESHOT, ++ "dra7xx-pcie-main", dra7xx); + if (ret) { + dev_err(dev, "failed to request irq\n"); +- goto err_gpio; ++ goto err_deinit; + } + + return 0; + ++err_deinit: ++ if (dra7xx->mode == DW_PCIE_RC_TYPE) ++ dw_pcie_host_deinit(&dra7xx->pci->pp); ++ else ++ dw_pcie_ep_deinit(&dra7xx->pci->ep); ++ + err_gpio: + err_get_sync: + pm_runtime_put(dev); +diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c +index 917c69edee1d54..dbd6d7a2748930 100644 +--- a/drivers/pci/controller/dwc/pci-imx6.c ++++ b/drivers/pci/controller/dwc/pci-imx6.c +@@ -958,7 +958,7 @@ static int imx6_pcie_host_init(struct dw_pcie_rp *pp) + ret = phy_power_on(imx6_pcie->phy); + if (ret) { + dev_err(dev, "waiting for PHY ready timeout!\n"); +- goto err_phy_off; ++ goto err_phy_exit; + } + } + +@@ -973,8 +973,9 @@ static int imx6_pcie_host_init(struct dw_pcie_rp *pp) + return 0; + + err_phy_off: +- if (imx6_pcie->phy) +- phy_exit(imx6_pcie->phy); ++ phy_power_off(imx6_pcie->phy); ++err_phy_exit: ++ phy_exit(imx6_pcie->phy); + err_clk_disable: + imx6_pcie_clk_disable(imx6_pcie); + err_reg_disable: +@@ -1118,6 +1119,8 @@ static int imx6_add_pcie_ep(struct imx6_pcie *imx6_pcie, + if (imx6_check_flag(imx6_pcie, IMX6_PCIE_FLAG_SUPPORT_64BIT)) + dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); + ++ ep->page_size = imx6_pcie->drvdata->epc_features->align; ++ + ret = dw_pcie_ep_init(ep); + if (ret) { + dev_err(dev, "failed to initialize endpoint\n"); +@@ -1578,7 +1581,8 @@ static const struct imx6_pcie_drvdata drvdata[] = { + }, + [IMX8MM_EP] = { + .variant = IMX8MM_EP, +- .flags = IMX6_PCIE_FLAG_HAS_PHYDRV, ++ .flags = IMX6_PCIE_FLAG_HAS_APP_RESET | ++ IMX6_PCIE_FLAG_HAS_PHYDRV, + .mode = DW_PCIE_EP_TYPE, + .gpr = "fsl,imx8mm-iomuxc-gpr", + .clk_names = imx8mm_clks, +@@ -1589,7 +1593,8 @@ static const struct imx6_pcie_drvdata drvdata[] = { + }, + [IMX8MP_EP] = { + .variant = IMX8MP_EP, +- .flags = IMX6_PCIE_FLAG_HAS_PHYDRV, ++ .flags = IMX6_PCIE_FLAG_HAS_APP_RESET | ++ IMX6_PCIE_FLAG_HAS_PHYDRV, + .mode = DW_PCIE_EP_TYPE, + .gpr = "fsl,imx8mp-iomuxc-gpr", + .clk_names = imx8mm_clks, +diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c +index 483c9540651353..d911f0e521da04 100644 +--- a/drivers/pci/controller/dwc/pci-keystone.c ++++ b/drivers/pci/controller/dwc/pci-keystone.c +@@ -577,7 +577,7 @@ static void ks_pcie_quirk(struct pci_dev *dev) + */ + if (pci_match_id(am6_pci_devids, bridge)) { + bridge_dev = pci_get_host_bridge_device(dev); +- if (!bridge_dev && !bridge_dev->parent) ++ if (!bridge_dev || !bridge_dev->parent) + return; + + ks_pcie = dev_get_drvdata(bridge_dev->parent); +diff --git a/drivers/pci/controller/dwc/pcie-kirin.c b/drivers/pci/controller/dwc/pcie-kirin.c +index d5523f3021024c..deab1e653b9a39 100644 +--- a/drivers/pci/controller/dwc/pcie-kirin.c ++++ b/drivers/pci/controller/dwc/pcie-kirin.c +@@ -412,12 +412,12 @@ static int kirin_pcie_parse_port(struct kirin_pcie *pcie, + if (pcie->gpio_id_reset[i] < 0) + continue; + +- pcie->num_slots++; +- if (pcie->num_slots > MAX_PCI_SLOTS) { ++ if (pcie->num_slots + 1 >= MAX_PCI_SLOTS) { + dev_err(dev, "Too many PCI slots!\n"); + ret = -EINVAL; + goto put_node; + } ++ pcie->num_slots++; + + ret = of_pci_get_devfn(child); + if (ret < 0) { +diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c b/drivers/pci/controller/dwc/pcie-qcom-ep.c +index 50b1635e3cbb1d..26cab226bccf4e 100644 +--- a/drivers/pci/controller/dwc/pcie-qcom-ep.c ++++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c +@@ -816,21 +816,15 @@ static int qcom_pcie_ep_probe(struct platform_device *pdev) + if (ret) + return ret; + +- ret = qcom_pcie_enable_resources(pcie_ep); +- if (ret) { +- dev_err(dev, "Failed to enable resources: %d\n", ret); +- return ret; +- } +- + ret = dw_pcie_ep_init(&pcie_ep->pci.ep); + if (ret) { + dev_err(dev, "Failed to initialize endpoint: %d\n", ret); +- goto err_disable_resources; ++ return ret; + } + + ret = qcom_pcie_ep_enable_irq_resources(pdev, pcie_ep); + if (ret) +- goto err_disable_resources; ++ goto err_ep_deinit; + + name = devm_kasprintf(dev, GFP_KERNEL, "%pOFP", dev->of_node); + if (!name) { +@@ -847,8 +841,8 @@ static int qcom_pcie_ep_probe(struct platform_device *pdev) + disable_irq(pcie_ep->global_irq); + disable_irq(pcie_ep->perst_irq); + +-err_disable_resources: +- qcom_pcie_disable_resources(pcie_ep); ++err_ep_deinit: ++ dw_pcie_ep_deinit(&pcie_ep->pci.ep); + + return ret; + } +diff --git a/drivers/pci/controller/pcie-xilinx-nwl.c b/drivers/pci/controller/pcie-xilinx-nwl.c +index 0408f4d612b5af..7417993f8cff76 100644 +--- a/drivers/pci/controller/pcie-xilinx-nwl.c ++++ b/drivers/pci/controller/pcie-xilinx-nwl.c +@@ -80,8 +80,8 @@ + #define MSGF_MISC_SR_NON_FATAL_DEV BIT(22) + #define MSGF_MISC_SR_FATAL_DEV BIT(23) + #define MSGF_MISC_SR_LINK_DOWN BIT(24) +-#define MSGF_MSIC_SR_LINK_AUTO_BWIDTH BIT(25) +-#define MSGF_MSIC_SR_LINK_BWIDTH BIT(26) ++#define MSGF_MISC_SR_LINK_AUTO_BWIDTH BIT(25) ++#define MSGF_MISC_SR_LINK_BWIDTH BIT(26) + + #define MSGF_MISC_SR_MASKALL (MSGF_MISC_SR_RXMSG_AVAIL | \ + MSGF_MISC_SR_RXMSG_OVER | \ +@@ -96,8 +96,8 @@ + MSGF_MISC_SR_NON_FATAL_DEV | \ + MSGF_MISC_SR_FATAL_DEV | \ + MSGF_MISC_SR_LINK_DOWN | \ +- MSGF_MSIC_SR_LINK_AUTO_BWIDTH | \ +- MSGF_MSIC_SR_LINK_BWIDTH) ++ MSGF_MISC_SR_LINK_AUTO_BWIDTH | \ ++ MSGF_MISC_SR_LINK_BWIDTH) + + /* Legacy interrupt status mask bits */ + #define MSGF_LEG_SR_INTA BIT(0) +@@ -299,10 +299,10 @@ static irqreturn_t nwl_pcie_misc_handler(int irq, void *data) + if (misc_stat & MSGF_MISC_SR_FATAL_DEV) + dev_err(dev, "Fatal Error Detected\n"); + +- if (misc_stat & MSGF_MSIC_SR_LINK_AUTO_BWIDTH) ++ if (misc_stat & MSGF_MISC_SR_LINK_AUTO_BWIDTH) + dev_info(dev, "Link Autonomous Bandwidth Management Status bit set\n"); + +- if (misc_stat & MSGF_MSIC_SR_LINK_BWIDTH) ++ if (misc_stat & MSGF_MISC_SR_LINK_BWIDTH) + dev_info(dev, "Link Bandwidth Management Status bit set\n"); + + /* Clear misc interrupt status */ +@@ -371,7 +371,7 @@ static void nwl_mask_intx_irq(struct irq_data *data) + u32 mask; + u32 val; + +- mask = 1 << (data->hwirq - 1); ++ mask = 1 << data->hwirq; + raw_spin_lock_irqsave(&pcie->leg_mask_lock, flags); + val = nwl_bridge_readl(pcie, MSGF_LEG_MASK); + nwl_bridge_writel(pcie, (val & (~mask)), MSGF_LEG_MASK); +@@ -385,7 +385,7 @@ static void nwl_unmask_intx_irq(struct irq_data *data) + u32 mask; + u32 val; + +- mask = 1 << (data->hwirq - 1); ++ mask = 1 << data->hwirq; + raw_spin_lock_irqsave(&pcie->leg_mask_lock, flags); + val = nwl_bridge_readl(pcie, MSGF_LEG_MASK); + nwl_bridge_writel(pcie, (val | mask), MSGF_LEG_MASK); +@@ -779,6 +779,7 @@ static int nwl_pcie_probe(struct platform_device *pdev) + return -ENODEV; + + pcie = pci_host_bridge_priv(bridge); ++ platform_set_drvdata(pdev, pcie); + + pcie->dev = dev; + +@@ -801,13 +802,13 @@ static int nwl_pcie_probe(struct platform_device *pdev) + err = nwl_pcie_bridge_init(pcie); + if (err) { + dev_err(dev, "HW Initialization failed\n"); +- return err; ++ goto err_clk; + } + + err = nwl_pcie_init_irq_domain(pcie); + if (err) { + dev_err(dev, "Failed creating IRQ Domain\n"); +- return err; ++ goto err_clk; + } + + bridge->sysdata = pcie; +@@ -817,11 +818,24 @@ static int nwl_pcie_probe(struct platform_device *pdev) + err = nwl_pcie_enable_msi(pcie); + if (err < 0) { + dev_err(dev, "failed to enable MSI support: %d\n", err); +- return err; ++ goto err_clk; + } + } + +- return pci_host_probe(bridge); ++ err = pci_host_probe(bridge); ++ if (!err) ++ return 0; ++ ++err_clk: ++ clk_disable_unprepare(pcie->clk); ++ return err; ++} ++ ++static void nwl_pcie_remove(struct platform_device *pdev) ++{ ++ struct nwl_pcie *pcie = platform_get_drvdata(pdev); ++ ++ clk_disable_unprepare(pcie->clk); + } + + static struct platform_driver nwl_pcie_driver = { +@@ -831,5 +845,6 @@ static struct platform_driver nwl_pcie_driver = { + .of_match_table = nwl_pcie_of_match, + }, + .probe = nwl_pcie_probe, ++ .remove_new = nwl_pcie_remove, + }; + builtin_platform_driver(nwl_pcie_driver); +diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c +index 8db214d4b1d464..4f77fe122e7d08 100644 +--- a/drivers/pci/pci.c ++++ b/drivers/pci/pci.c +@@ -1295,7 +1295,7 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout) + if (delay > PCI_RESET_WAIT) { + if (retrain) { + retrain = false; +- if (pcie_failed_link_retrain(bridge)) { ++ if (pcie_failed_link_retrain(bridge) == 0) { + delay = 1; + continue; + } +@@ -4647,7 +4647,15 @@ int pcie_retrain_link(struct pci_dev *pdev, bool use_lt) + pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_RL); + } + +- return pcie_wait_for_link_status(pdev, use_lt, !use_lt); ++ rc = pcie_wait_for_link_status(pdev, use_lt, !use_lt); ++ ++ /* ++ * Clear LBMS after a manual retrain so that the bit can be used ++ * to track link speed or width changes made by hardware itself ++ * in attempt to correct unreliable link operation. ++ */ ++ pcie_capability_write_word(pdev, PCI_EXP_LNKSTA, PCI_EXP_LNKSTA_LBMS); ++ return rc; + } + + /** +@@ -5598,8 +5606,10 @@ static void pci_bus_restore_locked(struct pci_bus *bus) + + list_for_each_entry(dev, &bus->devices, bus_list) { + pci_dev_restore(dev); +- if (dev->subordinate) ++ if (dev->subordinate) { ++ pci_bridge_wait_for_secondary_bus(dev, "bus reset"); + pci_bus_restore_locked(dev->subordinate); ++ } + } + } + +@@ -5633,8 +5643,10 @@ static void pci_slot_restore_locked(struct pci_slot *slot) + if (!dev->slot || dev->slot != slot) + continue; + pci_dev_restore(dev); +- if (dev->subordinate) ++ if (dev->subordinate) { ++ pci_bridge_wait_for_secondary_bus(dev, "slot reset"); + pci_bus_restore_locked(dev->subordinate); ++ } + } + } + +diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h +index fd44565c475628..55d76d6802ec88 100644 +--- a/drivers/pci/pci.h ++++ b/drivers/pci/pci.h +@@ -541,7 +541,7 @@ void pci_acs_init(struct pci_dev *dev); + int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags); + int pci_dev_specific_enable_acs(struct pci_dev *dev); + int pci_dev_specific_disable_acs_redir(struct pci_dev *dev); +-bool pcie_failed_link_retrain(struct pci_dev *dev); ++int pcie_failed_link_retrain(struct pci_dev *dev); + #else + static inline int pci_dev_specific_acs_enabled(struct pci_dev *dev, + u16 acs_flags) +@@ -556,9 +556,9 @@ static inline int pci_dev_specific_disable_acs_redir(struct pci_dev *dev) + { + return -ENOTTY; + } +-static inline bool pcie_failed_link_retrain(struct pci_dev *dev) ++static inline int pcie_failed_link_retrain(struct pci_dev *dev) + { +- return false; ++ return -ENOTTY; + } + #endif + +diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c +index 568410e64ce64e..206b76156c051a 100644 +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -66,7 +66,7 @@ + * apply this erratum workaround to any downstream ports as long as they + * support Link Active reporting and have the Link Control 2 register. + * Restrict the speed to 2.5GT/s then with the Target Link Speed field, +- * request a retrain and wait 200ms for the data link to go up. ++ * request a retrain and check the result. + * + * If this turns out successful and we know by the Vendor:Device ID it is + * safe to do so, then lift the restriction, letting the devices negotiate +@@ -74,33 +74,45 @@ + * firmware may have already arranged and lift it with ports that already + * report their data link being up. + * +- * Return TRUE if the link has been successfully retrained, otherwise FALSE. ++ * Otherwise revert the speed to the original setting and request a retrain ++ * again to remove any residual state, ignoring the result as it's supposed ++ * to fail anyway. ++ * ++ * Return 0 if the link has been successfully retrained. Return an error ++ * if retraining was not needed or we attempted a retrain and it failed. + */ +-bool pcie_failed_link_retrain(struct pci_dev *dev) ++int pcie_failed_link_retrain(struct pci_dev *dev) + { + static const struct pci_device_id ids[] = { + { PCI_VDEVICE(ASMEDIA, 0x2824) }, /* ASMedia ASM2824 */ + {} + }; + u16 lnksta, lnkctl2; ++ int ret = -ENOTTY; + + if (!pci_is_pcie(dev) || !pcie_downstream_port(dev) || + !pcie_cap_has_lnkctl2(dev) || !dev->link_active_reporting) +- return false; ++ return ret; + + pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &lnkctl2); + pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta); + if ((lnksta & (PCI_EXP_LNKSTA_LBMS | PCI_EXP_LNKSTA_DLLLA)) == + PCI_EXP_LNKSTA_LBMS) { ++ u16 oldlnkctl2 = lnkctl2; ++ + pci_info(dev, "broken device, retraining non-functional downstream link at 2.5GT/s\n"); + + lnkctl2 &= ~PCI_EXP_LNKCTL2_TLS; + lnkctl2 |= PCI_EXP_LNKCTL2_TLS_2_5GT; + pcie_capability_write_word(dev, PCI_EXP_LNKCTL2, lnkctl2); + +- if (pcie_retrain_link(dev, false)) { ++ ret = pcie_retrain_link(dev, false); ++ if (ret) { + pci_info(dev, "retraining failed\n"); +- return false; ++ pcie_capability_write_word(dev, PCI_EXP_LNKCTL2, ++ oldlnkctl2); ++ pcie_retrain_link(dev, true); ++ return ret; + } + + pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta); +@@ -117,13 +129,14 @@ bool pcie_failed_link_retrain(struct pci_dev *dev) + lnkctl2 |= lnkcap & PCI_EXP_LNKCAP_SLS; + pcie_capability_write_word(dev, PCI_EXP_LNKCTL2, lnkctl2); + +- if (pcie_retrain_link(dev, false)) { ++ ret = pcie_retrain_link(dev, false); ++ if (ret) { + pci_info(dev, "retraining failed\n"); +- return false; ++ return ret; + } + } + +- return true; ++ return ret; + } + + static ktime_t fixup_debug_start(struct pci_dev *dev, +diff --git a/drivers/perf/alibaba_uncore_drw_pmu.c b/drivers/perf/alibaba_uncore_drw_pmu.c +index 38a2947ae8130c..c6ff1bc7d336b8 100644 +--- a/drivers/perf/alibaba_uncore_drw_pmu.c ++++ b/drivers/perf/alibaba_uncore_drw_pmu.c +@@ -400,7 +400,7 @@ static irqreturn_t ali_drw_pmu_isr(int irq_num, void *data) + } + + /* clear common counter intr status */ +- clr_status = FIELD_PREP(ALI_DRW_PMCOM_CNT_OV_INTR_MASK, 1); ++ clr_status = FIELD_PREP(ALI_DRW_PMCOM_CNT_OV_INTR_MASK, status); + writel(clr_status, + drw_pmu->cfg_base + ALI_DRW_PMU_OV_INTR_CLR); + } +diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c +index e26ad1d3ed0bb7..058ea798b669b3 100644 +--- a/drivers/perf/arm-cmn.c ++++ b/drivers/perf/arm-cmn.c +@@ -24,14 +24,6 @@ + #define CMN_NI_NODE_ID GENMASK_ULL(31, 16) + #define CMN_NI_LOGICAL_ID GENMASK_ULL(47, 32) + +-#define CMN_NODEID_DEVID(reg) ((reg) & 3) +-#define CMN_NODEID_EXT_DEVID(reg) ((reg) & 1) +-#define CMN_NODEID_PID(reg) (((reg) >> 2) & 1) +-#define CMN_NODEID_EXT_PID(reg) (((reg) >> 1) & 3) +-#define CMN_NODEID_1x1_PID(reg) (((reg) >> 2) & 7) +-#define CMN_NODEID_X(reg, bits) ((reg) >> (3 + (bits))) +-#define CMN_NODEID_Y(reg, bits) (((reg) >> 3) & ((1U << (bits)) - 1)) +- + #define CMN_CHILD_INFO 0x0080 + #define CMN_CI_CHILD_COUNT GENMASK_ULL(15, 0) + #define CMN_CI_CHILD_PTR_OFFSET GENMASK_ULL(31, 16) +@@ -43,6 +35,9 @@ + #define CMN_MAX_XPS (CMN_MAX_DIMENSION * CMN_MAX_DIMENSION) + #define CMN_MAX_DTMS (CMN_MAX_XPS + (CMN_MAX_DIMENSION - 1) * 4) + ++/* Currently XPs are the node type we can have most of; others top out at 128 */ ++#define CMN_MAX_NODES_PER_EVENT CMN_MAX_XPS ++ + /* The CFG node has various info besides the discovery tree */ + #define CMN_CFGM_PERIPH_ID_01 0x0008 + #define CMN_CFGM_PID0_PART_0 GENMASK_ULL(7, 0) +@@ -78,7 +73,8 @@ + /* Technically this is 4 bits wide on DNs, but we only use 2 there anyway */ + #define CMN__PMU_OCCUP1_ID GENMASK_ULL(34, 32) + +-/* HN-Ps are weird... */ ++/* Some types are designed to coexist with another device in the same node */ ++#define CMN_CCLA_PMU_EVENT_SEL 0x008 + #define CMN_HNP_PMU_EVENT_SEL 0x008 + + /* DTMs live in the PMU space of XP registers */ +@@ -281,8 +277,11 @@ struct arm_cmn_node { + u16 id, logid; + enum cmn_node_type type; + ++ /* XP properties really, but replicated to children for convenience */ + u8 dtm; + s8 dtc; ++ u8 portid_bits:4; ++ u8 deviceid_bits:4; + /* DN/HN-F/CXHA */ + struct { + u8 val : 4; +@@ -358,49 +357,33 @@ struct arm_cmn { + static int arm_cmn_hp_state; + + struct arm_cmn_nodeid { +- u8 x; +- u8 y; + u8 port; + u8 dev; + }; + + static int arm_cmn_xyidbits(const struct arm_cmn *cmn) + { +- return fls((cmn->mesh_x - 1) | (cmn->mesh_y - 1) | 2); ++ return fls((cmn->mesh_x - 1) | (cmn->mesh_y - 1)); + } + +-static struct arm_cmn_nodeid arm_cmn_nid(const struct arm_cmn *cmn, u16 id) ++static struct arm_cmn_nodeid arm_cmn_nid(const struct arm_cmn_node *dn) + { + struct arm_cmn_nodeid nid; + +- if (cmn->num_xps == 1) { +- nid.x = 0; +- nid.y = 0; +- nid.port = CMN_NODEID_1x1_PID(id); +- nid.dev = CMN_NODEID_DEVID(id); +- } else { +- int bits = arm_cmn_xyidbits(cmn); +- +- nid.x = CMN_NODEID_X(id, bits); +- nid.y = CMN_NODEID_Y(id, bits); +- if (cmn->ports_used & 0xc) { +- nid.port = CMN_NODEID_EXT_PID(id); +- nid.dev = CMN_NODEID_EXT_DEVID(id); +- } else { +- nid.port = CMN_NODEID_PID(id); +- nid.dev = CMN_NODEID_DEVID(id); +- } +- } ++ nid.dev = dn->id & ((1U << dn->deviceid_bits) - 1); ++ nid.port = (dn->id >> dn->deviceid_bits) & ((1U << dn->portid_bits) - 1); + return nid; + } + + static struct arm_cmn_node *arm_cmn_node_to_xp(const struct arm_cmn *cmn, + const struct arm_cmn_node *dn) + { +- struct arm_cmn_nodeid nid = arm_cmn_nid(cmn, dn->id); +- int xp_idx = cmn->mesh_x * nid.y + nid.x; ++ int id = dn->id >> (dn->portid_bits + dn->deviceid_bits); ++ int bits = arm_cmn_xyidbits(cmn); ++ int x = id >> bits; ++ int y = id & ((1U << bits) - 1); + +- return cmn->xps + xp_idx; ++ return cmn->xps + cmn->mesh_x * y + x; + } + static struct arm_cmn_node *arm_cmn_node(const struct arm_cmn *cmn, + enum cmn_node_type type) +@@ -486,13 +469,13 @@ static const char *arm_cmn_device_type(u8 type) + } + } + +-static void arm_cmn_show_logid(struct seq_file *s, int x, int y, int p, int d) ++static void arm_cmn_show_logid(struct seq_file *s, const struct arm_cmn_node *xp, int p, int d) + { + struct arm_cmn *cmn = s->private; + struct arm_cmn_node *dn; ++ u16 id = xp->id | d | (p << xp->deviceid_bits); + + for (dn = cmn->dns; dn->type; dn++) { +- struct arm_cmn_nodeid nid = arm_cmn_nid(cmn, dn->id); + int pad = dn->logid < 10; + + if (dn->type == CMN_TYPE_XP) +@@ -501,7 +484,7 @@ static void arm_cmn_show_logid(struct seq_file *s, int x, int y, int p, int d) + if (dn->type < CMN_TYPE_HNI) + continue; + +- if (nid.x != x || nid.y != y || nid.port != p || nid.dev != d) ++ if (dn->id != id) + continue; + + seq_printf(s, " %*c#%-*d |", pad + 1, ' ', 3 - pad, dn->logid); +@@ -522,6 +505,7 @@ static int arm_cmn_map_show(struct seq_file *s, void *data) + y = cmn->mesh_y; + while (y--) { + int xp_base = cmn->mesh_x * y; ++ struct arm_cmn_node *xp = cmn->xps + xp_base; + u8 port[CMN_MAX_PORTS][CMN_MAX_DIMENSION]; + + for (x = 0; x < cmn->mesh_x; x++) +@@ -529,16 +513,14 @@ static int arm_cmn_map_show(struct seq_file *s, void *data) + + seq_printf(s, "\n%-2d |", y); + for (x = 0; x < cmn->mesh_x; x++) { +- struct arm_cmn_node *xp = cmn->xps + xp_base + x; +- + for (p = 0; p < CMN_MAX_PORTS; p++) +- port[p][x] = arm_cmn_device_connect_info(cmn, xp, p); ++ port[p][x] = arm_cmn_device_connect_info(cmn, xp + x, p); + seq_printf(s, " XP #%-3d|", xp_base + x); + } + + seq_puts(s, "\n |"); + for (x = 0; x < cmn->mesh_x; x++) { +- s8 dtc = cmn->xps[xp_base + x].dtc; ++ s8 dtc = xp[x].dtc; + + if (dtc < 0) + seq_puts(s, " DTC ?? |"); +@@ -555,10 +537,10 @@ static int arm_cmn_map_show(struct seq_file *s, void *data) + seq_puts(s, arm_cmn_device_type(port[p][x])); + seq_puts(s, "\n 0|"); + for (x = 0; x < cmn->mesh_x; x++) +- arm_cmn_show_logid(s, x, y, p, 0); ++ arm_cmn_show_logid(s, xp + x, p, 0); + seq_puts(s, "\n 1|"); + for (x = 0; x < cmn->mesh_x; x++) +- arm_cmn_show_logid(s, x, y, p, 1); ++ arm_cmn_show_logid(s, xp + x, p, 1); + } + seq_puts(s, "\n-----+"); + } +@@ -586,7 +568,7 @@ static void arm_cmn_debugfs_init(struct arm_cmn *cmn, int id) {} + + struct arm_cmn_hw_event { + struct arm_cmn_node *dn; +- u64 dtm_idx[4]; ++ u64 dtm_idx[DIV_ROUND_UP(CMN_MAX_NODES_PER_EVENT * 2, 64)]; + s8 dtc_idx[CMN_MAX_DTCS]; + u8 num_dns; + u8 dtm_offset; +@@ -1753,10 +1735,7 @@ static int arm_cmn_event_init(struct perf_event *event) + } + + if (!hw->num_dns) { +- struct arm_cmn_nodeid nid = arm_cmn_nid(cmn, nodeid); +- +- dev_dbg(cmn->dev, "invalid node 0x%x (%d,%d,%d,%d) type 0x%x\n", +- nodeid, nid.x, nid.y, nid.port, nid.dev, type); ++ dev_dbg(cmn->dev, "invalid node 0x%x type 0x%x\n", nodeid, type); + return -EINVAL; + } + +@@ -1851,7 +1830,7 @@ static int arm_cmn_event_add(struct perf_event *event, int flags) + dtm->wp_event[wp_idx] = hw->dtc_idx[d]; + writel_relaxed(cfg, dtm->base + CMN_DTM_WPn_CONFIG(wp_idx)); + } else { +- struct arm_cmn_nodeid nid = arm_cmn_nid(cmn, dn->id); ++ struct arm_cmn_nodeid nid = arm_cmn_nid(dn); + + if (cmn->multi_dtm) + nid.port %= 2; +@@ -2098,10 +2077,12 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn) + continue; + + xp = arm_cmn_node_to_xp(cmn, dn); ++ dn->portid_bits = xp->portid_bits; ++ dn->deviceid_bits = xp->deviceid_bits; + dn->dtc = xp->dtc; + dn->dtm = xp->dtm; + if (cmn->multi_dtm) +- dn->dtm += arm_cmn_nid(cmn, dn->id).port / 2; ++ dn->dtm += arm_cmn_nid(dn).port / 2; + + if (dn->type == CMN_TYPE_DTC) { + int err = arm_cmn_init_dtc(cmn, dn, dtc_idx++); +@@ -2271,18 +2252,27 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset) + arm_cmn_init_dtm(dtm++, xp, 0); + /* + * Keeping track of connected ports will let us filter out +- * unnecessary XP events easily. We can also reliably infer the +- * "extra device ports" configuration for the node ID format +- * from this, since in that case we will see at least one XP +- * with port 2 connected, for the HN-D. ++ * unnecessary XP events easily, and also infer the per-XP ++ * part of the node ID format. + */ + for (int p = 0; p < CMN_MAX_PORTS; p++) + if (arm_cmn_device_connect_info(cmn, xp, p)) + xp_ports |= BIT(p); + +- if (cmn->multi_dtm && (xp_ports & 0xc)) ++ if (cmn->num_xps == 1) { ++ xp->portid_bits = 3; ++ xp->deviceid_bits = 2; ++ } else if (xp_ports > 0x3) { ++ xp->portid_bits = 2; ++ xp->deviceid_bits = 1; ++ } else { ++ xp->portid_bits = 1; ++ xp->deviceid_bits = 2; ++ } ++ ++ if (cmn->multi_dtm && (xp_ports > 0x3)) + arm_cmn_init_dtm(dtm++, xp, 1); +- if (cmn->multi_dtm && (xp_ports & 0x30)) ++ if (cmn->multi_dtm && (xp_ports > 0xf)) + arm_cmn_init_dtm(dtm++, xp, 2); + + cmn->ports_used |= xp_ports; +@@ -2337,10 +2327,13 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset) + case CMN_TYPE_CXHA: + case CMN_TYPE_CCRA: + case CMN_TYPE_CCHA: +- case CMN_TYPE_CCLA: + case CMN_TYPE_HNS: + dn++; + break; ++ case CMN_TYPE_CCLA: ++ dn->pmu_base += CMN_CCLA_PMU_EVENT_SEL; ++ dn++; ++ break; + /* Nothing to see here */ + case CMN_TYPE_MPAM_S: + case CMN_TYPE_MPAM_NS: +@@ -2358,7 +2351,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset) + case CMN_TYPE_HNP: + case CMN_TYPE_CCLA_RNI: + dn[1] = dn[0]; +- dn[0].pmu_base += CMN_HNP_PMU_EVENT_SEL; ++ dn[0].pmu_base += CMN_CCLA_PMU_EVENT_SEL; + dn[1].type = arm_cmn_subtype(dn->type); + dn += 2; + break; +diff --git a/drivers/perf/dwc_pcie_pmu.c b/drivers/perf/dwc_pcie_pmu.c +index c5e328f2384194..f205ecad2e4c06 100644 +--- a/drivers/perf/dwc_pcie_pmu.c ++++ b/drivers/perf/dwc_pcie_pmu.c +@@ -556,10 +556,10 @@ static int dwc_pcie_register_dev(struct pci_dev *pdev) + { + struct platform_device *plat_dev; + struct dwc_pcie_dev_info *dev_info; +- u32 bdf; ++ u32 sbdf; + +- bdf = PCI_DEVID(pdev->bus->number, pdev->devfn); +- plat_dev = platform_device_register_data(NULL, "dwc_pcie_pmu", bdf, ++ sbdf = (pci_domain_nr(pdev->bus) << 16) | PCI_DEVID(pdev->bus->number, pdev->devfn); ++ plat_dev = platform_device_register_data(NULL, "dwc_pcie_pmu", sbdf, + pdev, sizeof(*pdev)); + + if (IS_ERR(plat_dev)) +@@ -611,15 +611,15 @@ static int dwc_pcie_pmu_probe(struct platform_device *plat_dev) + struct pci_dev *pdev = plat_dev->dev.platform_data; + struct dwc_pcie_pmu *pcie_pmu; + char *name; +- u32 bdf, val; ++ u32 sbdf, val; + u16 vsec; + int ret; + + vsec = pci_find_vsec_capability(pdev, pdev->vendor, + DWC_PCIE_VSEC_RAS_DES_ID); + pci_read_config_dword(pdev, vsec + PCI_VNDR_HEADER, &val); +- bdf = PCI_DEVID(pdev->bus->number, pdev->devfn); +- name = devm_kasprintf(&plat_dev->dev, GFP_KERNEL, "dwc_rootport_%x", bdf); ++ sbdf = plat_dev->id; ++ name = devm_kasprintf(&plat_dev->dev, GFP_KERNEL, "dwc_rootport_%x", sbdf); + if (!name) + return -ENOMEM; + +@@ -650,7 +650,7 @@ static int dwc_pcie_pmu_probe(struct platform_device *plat_dev) + ret = cpuhp_state_add_instance(dwc_pcie_pmu_hp_state, + &pcie_pmu->cpuhp_node); + if (ret) { +- pci_err(pdev, "Error %d registering hotplug @%x\n", ret, bdf); ++ pci_err(pdev, "Error %d registering hotplug @%x\n", ret, sbdf); + return ret; + } + +@@ -663,7 +663,7 @@ static int dwc_pcie_pmu_probe(struct platform_device *plat_dev) + + ret = perf_pmu_register(&pcie_pmu->pmu, name, -1); + if (ret) { +- pci_err(pdev, "Error %d registering PMU @%x\n", ret, bdf); ++ pci_err(pdev, "Error %d registering PMU @%x\n", ret, sbdf); + return ret; + } + ret = devm_add_action_or_reset(&plat_dev->dev, dwc_pcie_unregister_pmu, +@@ -726,7 +726,6 @@ static struct platform_driver dwc_pcie_pmu_driver = { + static int __init dwc_pcie_pmu_init(void) + { + struct pci_dev *pdev = NULL; +- bool found = false; + int ret; + + for_each_pci_dev(pdev) { +@@ -738,11 +737,7 @@ static int __init dwc_pcie_pmu_init(void) + pci_dev_put(pdev); + return ret; + } +- +- found = true; + } +- if (!found) +- return -ENODEV; + + ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, + "perf/dwc_pcie_pmu:online", +diff --git a/drivers/perf/hisilicon/hisi_pcie_pmu.c b/drivers/perf/hisilicon/hisi_pcie_pmu.c +index f06027574a241a..f7d6c59d993016 100644 +--- a/drivers/perf/hisilicon/hisi_pcie_pmu.c ++++ b/drivers/perf/hisilicon/hisi_pcie_pmu.c +@@ -208,7 +208,7 @@ static void hisi_pcie_pmu_writeq(struct hisi_pcie_pmu *pcie_pmu, u32 reg_offset, + static u64 hisi_pcie_pmu_get_event_ctrl_val(struct perf_event *event) + { + u64 port, trig_len, thr_len, len_mode; +- u64 reg = HISI_PCIE_INIT_SET; ++ u64 reg = 0; + + /* Config HISI_PCIE_EVENT_CTRL according to event. */ + reg |= FIELD_PREP(HISI_PCIE_EVENT_M, hisi_pcie_get_real_event(event)); +@@ -452,10 +452,24 @@ static void hisi_pcie_pmu_set_period(struct perf_event *event) + struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + int idx = hwc->idx; ++ u64 orig_cnt, cnt; ++ ++ orig_cnt = hisi_pcie_pmu_read_counter(event); + + local64_set(&hwc->prev_count, HISI_PCIE_INIT_VAL); + hisi_pcie_pmu_writeq(pcie_pmu, HISI_PCIE_CNT, idx, HISI_PCIE_INIT_VAL); + hisi_pcie_pmu_writeq(pcie_pmu, HISI_PCIE_EXT_CNT, idx, HISI_PCIE_INIT_VAL); ++ ++ /* ++ * The counter maybe unwritable if the target event is unsupported. ++ * Check this by comparing the counts after setting the period. If ++ * the counts stay unchanged after setting the period then update ++ * the hwc->prev_count correctly. Otherwise the final counts user ++ * get maybe totally wrong. ++ */ ++ cnt = hisi_pcie_pmu_read_counter(event); ++ if (orig_cnt == cnt) ++ local64_set(&hwc->prev_count, cnt); + } + + static void hisi_pcie_pmu_enable_counter(struct hisi_pcie_pmu *pcie_pmu, struct hw_perf_event *hwc) +diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +index 946c01210ac8c0..3bd9b62b23dcc2 100644 +--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c ++++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +@@ -15,6 +15,7 @@ + #include <linux/of_platform.h> + #include <linux/phy/phy.h> + #include <linux/platform_device.h> ++#include <linux/pm_runtime.h> + #include <linux/rational.h> + #include <linux/regmap.h> + #include <linux/reset.h> +diff --git a/drivers/pinctrl/mvebu/pinctrl-dove.c b/drivers/pinctrl/mvebu/pinctrl-dove.c +index 1947da73e51210..dce601d993728c 100644 +--- a/drivers/pinctrl/mvebu/pinctrl-dove.c ++++ b/drivers/pinctrl/mvebu/pinctrl-dove.c +@@ -767,7 +767,7 @@ static int dove_pinctrl_probe(struct platform_device *pdev) + struct resource fb_res; + struct mvebu_mpp_ctrl_data *mpp_data; + void __iomem *base; +- int i; ++ int i, ret; + + pdev->dev.platform_data = (void *)device_get_match_data(&pdev->dev); + +@@ -783,13 +783,17 @@ static int dove_pinctrl_probe(struct platform_device *pdev) + clk_prepare_enable(clk); + + base = devm_platform_get_and_ioremap_resource(pdev, 0, &mpp_res); +- if (IS_ERR(base)) +- return PTR_ERR(base); ++ if (IS_ERR(base)) { ++ ret = PTR_ERR(base); ++ goto err_probe; ++ } + + mpp_data = devm_kcalloc(&pdev->dev, dove_pinctrl_info.ncontrols, + sizeof(*mpp_data), GFP_KERNEL); +- if (!mpp_data) +- return -ENOMEM; ++ if (!mpp_data) { ++ ret = -ENOMEM; ++ goto err_probe; ++ } + + dove_pinctrl_info.control_data = mpp_data; + for (i = 0; i < ARRAY_SIZE(dove_mpp_controls); i++) +@@ -808,8 +812,10 @@ static int dove_pinctrl_probe(struct platform_device *pdev) + } + + mpp4_base = devm_ioremap_resource(&pdev->dev, res); +- if (IS_ERR(mpp4_base)) +- return PTR_ERR(mpp4_base); ++ if (IS_ERR(mpp4_base)) { ++ ret = PTR_ERR(mpp4_base); ++ goto err_probe; ++ } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 2); + if (!res) { +@@ -820,8 +826,10 @@ static int dove_pinctrl_probe(struct platform_device *pdev) + } + + pmu_base = devm_ioremap_resource(&pdev->dev, res); +- if (IS_ERR(pmu_base)) +- return PTR_ERR(pmu_base); ++ if (IS_ERR(pmu_base)) { ++ ret = PTR_ERR(pmu_base); ++ goto err_probe; ++ } + + gconfmap = syscon_regmap_lookup_by_compatible("marvell,dove-global-config"); + if (IS_ERR(gconfmap)) { +@@ -831,12 +839,17 @@ static int dove_pinctrl_probe(struct platform_device *pdev) + adjust_resource(&fb_res, + (mpp_res->start & INT_REGS_MASK) + GC_REGS_OFFS, 0x14); + gc_base = devm_ioremap_resource(&pdev->dev, &fb_res); +- if (IS_ERR(gc_base)) +- return PTR_ERR(gc_base); ++ if (IS_ERR(gc_base)) { ++ ret = PTR_ERR(gc_base); ++ goto err_probe; ++ } ++ + gconfmap = devm_regmap_init_mmio(&pdev->dev, + gc_base, &gc_regmap_config); +- if (IS_ERR(gconfmap)) +- return PTR_ERR(gconfmap); ++ if (IS_ERR(gconfmap)) { ++ ret = PTR_ERR(gconfmap); ++ goto err_probe; ++ } + } + + /* Warn on any missing DT resource */ +@@ -844,6 +857,9 @@ static int dove_pinctrl_probe(struct platform_device *pdev) + dev_warn(&pdev->dev, FW_BUG "Missing pinctrl regs in DTB. Please update your firmware.\n"); + + return mvebu_pinctrl_probe(pdev); ++err_probe: ++ clk_disable_unprepare(clk); ++ return ret; + } + + static struct platform_driver dove_pinctrl_driver = { +diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c +index 4da3c3f422b691..2ec599e383e4b2 100644 +--- a/drivers/pinctrl/pinctrl-single.c ++++ b/drivers/pinctrl/pinctrl-single.c +@@ -1913,7 +1913,8 @@ static int pcs_probe(struct platform_device *pdev) + + dev_info(pcs->dev, "%i pins, size %u\n", pcs->desc.npins, pcs->size); + +- if (pinctrl_enable(pcs->pctl)) ++ ret = pinctrl_enable(pcs->pctl); ++ if (ret) + goto free; + + return 0; +diff --git a/drivers/pinctrl/ti/pinctrl-ti-iodelay.c b/drivers/pinctrl/ti/pinctrl-ti-iodelay.c +index ef97586385019a..451801acdc4038 100644 +--- a/drivers/pinctrl/ti/pinctrl-ti-iodelay.c ++++ b/drivers/pinctrl/ti/pinctrl-ti-iodelay.c +@@ -273,6 +273,22 @@ static int ti_iodelay_pinconf_set(struct ti_iodelay_device *iod, + return r; + } + ++/** ++ * ti_iodelay_pinconf_deinit_dev() - deinit the iodelay device ++ * @data: IODelay device ++ * ++ * Deinitialize the IODelay device (basically just lock the region back up. ++ */ ++static void ti_iodelay_pinconf_deinit_dev(void *data) ++{ ++ struct ti_iodelay_device *iod = data; ++ const struct ti_iodelay_reg_data *reg = iod->reg_data; ++ ++ /* lock the iodelay region back again */ ++ regmap_update_bits(iod->regmap, reg->reg_global_lock_offset, ++ reg->global_lock_mask, reg->global_lock_val); ++} ++ + /** + * ti_iodelay_pinconf_init_dev() - Initialize IODelay device + * @iod: iodelay device +@@ -295,6 +311,11 @@ static int ti_iodelay_pinconf_init_dev(struct ti_iodelay_device *iod) + if (r) + return r; + ++ r = devm_add_action_or_reset(iod->dev, ti_iodelay_pinconf_deinit_dev, ++ iod); ++ if (r) ++ return r; ++ + /* Read up Recalibration sequence done by bootloader */ + r = regmap_read(iod->regmap, reg->reg_refclk_offset, &val); + if (r) +@@ -353,21 +374,6 @@ static int ti_iodelay_pinconf_init_dev(struct ti_iodelay_device *iod) + return 0; + } + +-/** +- * ti_iodelay_pinconf_deinit_dev() - deinit the iodelay device +- * @iod: IODelay device +- * +- * Deinitialize the IODelay device (basically just lock the region back up. +- */ +-static void ti_iodelay_pinconf_deinit_dev(struct ti_iodelay_device *iod) +-{ +- const struct ti_iodelay_reg_data *reg = iod->reg_data; +- +- /* lock the iodelay region back again */ +- regmap_update_bits(iod->regmap, reg->reg_global_lock_offset, +- reg->global_lock_mask, reg->global_lock_val); +-} +- + /** + * ti_iodelay_get_pingroup() - Find the group mapped by a group selector + * @iod: iodelay device +@@ -822,53 +828,48 @@ MODULE_DEVICE_TABLE(of, ti_iodelay_of_match); + static int ti_iodelay_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +- struct device_node *np = of_node_get(dev->of_node); ++ struct device_node *np __free(device_node) = of_node_get(dev->of_node); + struct resource *res; + struct ti_iodelay_device *iod; +- int ret = 0; ++ int ret; + + if (!np) { +- ret = -EINVAL; + dev_err(dev, "No OF node\n"); +- goto exit_out; ++ return -EINVAL; + } + + iod = devm_kzalloc(dev, sizeof(*iod), GFP_KERNEL); +- if (!iod) { +- ret = -ENOMEM; +- goto exit_out; +- } ++ if (!iod) ++ return -ENOMEM; ++ + iod->dev = dev; + iod->reg_data = device_get_match_data(dev); + if (!iod->reg_data) { +- ret = -EINVAL; + dev_err(dev, "No DATA match\n"); +- goto exit_out; ++ return -EINVAL; + } + + /* So far We can assume there is only 1 bank of registers */ + iod->reg_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); +- if (IS_ERR(iod->reg_base)) { +- ret = PTR_ERR(iod->reg_base); +- goto exit_out; +- } ++ if (IS_ERR(iod->reg_base)) ++ return PTR_ERR(iod->reg_base); ++ + iod->phys_base = res->start; + + iod->regmap = devm_regmap_init_mmio(dev, iod->reg_base, + iod->reg_data->regmap_config); + if (IS_ERR(iod->regmap)) { + dev_err(dev, "Regmap MMIO init failed.\n"); +- ret = PTR_ERR(iod->regmap); +- goto exit_out; ++ return PTR_ERR(iod->regmap); + } + + ret = ti_iodelay_pinconf_init_dev(iod); + if (ret) +- goto exit_out; ++ return ret; + + ret = ti_iodelay_alloc_pins(dev, iod, res->start); + if (ret) +- goto exit_out; ++ return ret; + + iod->desc.pctlops = &ti_iodelay_pinctrl_ops; + /* no pinmux ops - we are pinconf */ +@@ -879,38 +880,14 @@ static int ti_iodelay_probe(struct platform_device *pdev) + ret = devm_pinctrl_register_and_init(dev, &iod->desc, iod, &iod->pctl); + if (ret) { + dev_err(dev, "Failed to register pinctrl\n"); +- goto exit_out; ++ return ret; + } + +- platform_set_drvdata(pdev, iod); +- +- ret = pinctrl_enable(iod->pctl); +- if (ret) +- goto exit_out; +- +- return 0; +- +-exit_out: +- of_node_put(np); +- return ret; +-} +- +-/** +- * ti_iodelay_remove() - standard remove +- * @pdev: platform device +- */ +-static void ti_iodelay_remove(struct platform_device *pdev) +-{ +- struct ti_iodelay_device *iod = platform_get_drvdata(pdev); +- +- ti_iodelay_pinconf_deinit_dev(iod); +- +- /* Expect other allocations to be freed by devm */ ++ return pinctrl_enable(iod->pctl); + } + + static struct platform_driver ti_iodelay_driver = { + .probe = ti_iodelay_probe, +- .remove_new = ti_iodelay_remove, + .driver = { + .name = DRIVER_NAME, + .of_match_table = ti_iodelay_of_match, +diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c +index 490815917adec8..32293df50bb1cc 100644 +--- a/drivers/platform/x86/ideapad-laptop.c ++++ b/drivers/platform/x86/ideapad-laptop.c +@@ -422,13 +422,14 @@ static ssize_t camera_power_show(struct device *dev, + char *buf) + { + struct ideapad_private *priv = dev_get_drvdata(dev); +- unsigned long result; ++ unsigned long result = 0; + int err; + +- scoped_guard(mutex, &priv->vpc_mutex) ++ scoped_guard(mutex, &priv->vpc_mutex) { + err = read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &result); +- if (err) +- return err; ++ if (err) ++ return err; ++ } + + return sysfs_emit(buf, "%d\n", !!result); + } +@@ -445,10 +446,11 @@ static ssize_t camera_power_store(struct device *dev, + if (err) + return err; + +- scoped_guard(mutex, &priv->vpc_mutex) ++ scoped_guard(mutex, &priv->vpc_mutex) { + err = write_ec_cmd(priv->adev->handle, VPCCMD_W_CAMERA, state); +- if (err) +- return err; ++ if (err) ++ return err; ++ } + + return count; + } +@@ -496,13 +498,14 @@ static ssize_t fan_mode_show(struct device *dev, + char *buf) + { + struct ideapad_private *priv = dev_get_drvdata(dev); +- unsigned long result; ++ unsigned long result = 0; + int err; + +- scoped_guard(mutex, &priv->vpc_mutex) ++ scoped_guard(mutex, &priv->vpc_mutex) { + err = read_ec_data(priv->adev->handle, VPCCMD_R_FAN, &result); +- if (err) +- return err; ++ if (err) ++ return err; ++ } + + return sysfs_emit(buf, "%lu\n", result); + } +@@ -522,10 +525,11 @@ static ssize_t fan_mode_store(struct device *dev, + if (state > 4 || state == 3) + return -EINVAL; + +- scoped_guard(mutex, &priv->vpc_mutex) ++ scoped_guard(mutex, &priv->vpc_mutex) { + err = write_ec_cmd(priv->adev->handle, VPCCMD_W_FAN, state); +- if (err) +- return err; ++ if (err) ++ return err; ++ } + + return count; + } +@@ -605,13 +609,14 @@ static ssize_t touchpad_show(struct device *dev, + char *buf) + { + struct ideapad_private *priv = dev_get_drvdata(dev); +- unsigned long result; ++ unsigned long result = 0; + int err; + +- scoped_guard(mutex, &priv->vpc_mutex) ++ scoped_guard(mutex, &priv->vpc_mutex) { + err = read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &result); +- if (err) +- return err; ++ if (err) ++ return err; ++ } + + priv->r_touchpad_val = result; + +@@ -630,10 +635,11 @@ static ssize_t touchpad_store(struct device *dev, + if (err) + return err; + +- scoped_guard(mutex, &priv->vpc_mutex) ++ scoped_guard(mutex, &priv->vpc_mutex) { + err = write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, state); +- if (err) +- return err; ++ if (err) ++ return err; ++ } + + priv->r_touchpad_val = state; + +diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c +index 623d15b68707ec..0ab6008e863e82 100644 +--- a/drivers/pmdomain/core.c ++++ b/drivers/pmdomain/core.c +@@ -3153,7 +3153,7 @@ static int genpd_summary_one(struct seq_file *s, + else + snprintf(state, sizeof(state), "%s", + status_lookup[genpd->status]); +- seq_printf(s, "%-30s %-50s %u", genpd->name, state, genpd->performance_state); ++ seq_printf(s, "%-30s %-49s %u", genpd->name, state, genpd->performance_state); + + /* + * Modifications on the list require holding locks on both +diff --git a/drivers/power/supply/axp20x_battery.c b/drivers/power/supply/axp20x_battery.c +index 6ac5c80cfda214..7520b599eb3d17 100644 +--- a/drivers/power/supply/axp20x_battery.c ++++ b/drivers/power/supply/axp20x_battery.c +@@ -303,11 +303,11 @@ static int axp20x_battery_get_prop(struct power_supply *psy, + val->intval = reg & AXP209_FG_PERCENT; + break; + +- case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: ++ case POWER_SUPPLY_PROP_VOLTAGE_MAX: + return axp20x_batt->data->get_max_voltage(axp20x_batt, + &val->intval); + +- case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: ++ case POWER_SUPPLY_PROP_VOLTAGE_MIN: + ret = regmap_read(axp20x_batt->regmap, AXP20X_V_OFF, ®); + if (ret) + return ret; +@@ -455,10 +455,10 @@ static int axp20x_battery_set_prop(struct power_supply *psy, + struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy); + + switch (psp) { +- case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: ++ case POWER_SUPPLY_PROP_VOLTAGE_MIN: + return axp20x_set_voltage_min_design(axp20x_batt, val->intval); + +- case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: ++ case POWER_SUPPLY_PROP_VOLTAGE_MAX: + return axp20x_batt->data->set_max_voltage(axp20x_batt, val->intval); + + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: +@@ -493,8 +493,8 @@ static enum power_supply_property axp20x_battery_props[] = { + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, + POWER_SUPPLY_PROP_HEALTH, +- POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, +- POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, ++ POWER_SUPPLY_PROP_VOLTAGE_MAX, ++ POWER_SUPPLY_PROP_VOLTAGE_MIN, + POWER_SUPPLY_PROP_CAPACITY, + }; + +@@ -502,8 +502,8 @@ static int axp20x_battery_prop_writeable(struct power_supply *psy, + enum power_supply_property psp) + { + return psp == POWER_SUPPLY_PROP_STATUS || +- psp == POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN || +- psp == POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN || ++ psp == POWER_SUPPLY_PROP_VOLTAGE_MIN || ++ psp == POWER_SUPPLY_PROP_VOLTAGE_MAX || + psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT || + psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX; + } +diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c +index e7d37e422c3f6e..496c3e1f2ee6d6 100644 +--- a/drivers/power/supply/max17042_battery.c ++++ b/drivers/power/supply/max17042_battery.c +@@ -853,7 +853,10 @@ static void max17042_set_soc_threshold(struct max17042_chip *chip, u16 off) + /* program interrupt thresholds such that we should + * get interrupt for every 'off' perc change in the soc + */ +- regmap_read(map, MAX17042_RepSOC, &soc); ++ if (chip->pdata->enable_current_sense) ++ regmap_read(map, MAX17042_RepSOC, &soc); ++ else ++ regmap_read(map, MAX17042_VFSOC, &soc); + soc >>= 8; + soc_tr = (soc + off) << 8; + if (off < soc) +diff --git a/drivers/powercap/intel_rapl_common.c b/drivers/powercap/intel_rapl_common.c +index 8e7f4c0473ab94..9bf9ed9a6a54f7 100644 +--- a/drivers/powercap/intel_rapl_common.c ++++ b/drivers/powercap/intel_rapl_common.c +@@ -740,7 +740,7 @@ static struct rapl_primitive_info *get_rpi(struct rapl_package *rp, int prim) + { + struct rapl_primitive_info *rpi = rp->priv->rpi; + +- if (prim < 0 || prim > NR_RAPL_PRIMITIVES || !rpi) ++ if (prim < 0 || prim >= NR_RAPL_PRIMITIVES || !rpi) + return NULL; + + return &rpi[prim]; +diff --git a/drivers/pps/clients/pps_parport.c b/drivers/pps/clients/pps_parport.c +index af972cdc04b53c..53e9c304ae0a7a 100644 +--- a/drivers/pps/clients/pps_parport.c ++++ b/drivers/pps/clients/pps_parport.c +@@ -149,6 +149,9 @@ static void parport_attach(struct parport *port) + } + + index = ida_alloc(&pps_client_index, GFP_KERNEL); ++ if (index < 0) ++ goto err_free_device; ++ + memset(&pps_client_cb, 0, sizeof(pps_client_cb)); + pps_client_cb.private = device; + pps_client_cb.irq_func = parport_irq; +@@ -159,7 +162,7 @@ static void parport_attach(struct parport *port) + index); + if (!device->pardev) { + pr_err("couldn't register with %s\n", port->name); +- goto err_free; ++ goto err_free_ida; + } + + if (parport_claim_or_block(device->pardev) < 0) { +@@ -187,8 +190,9 @@ static void parport_attach(struct parport *port) + parport_release(device->pardev); + err_unregister_dev: + parport_unregister_device(device->pardev); +-err_free: ++err_free_ida: + ida_free(&pps_client_index, index); ++err_free_device: + kfree(device); + } + +diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c +index 03afc160fc72ce..86b680adbf01c7 100644 +--- a/drivers/regulator/of_regulator.c ++++ b/drivers/regulator/of_regulator.c +@@ -777,7 +777,7 @@ int of_regulator_bulk_get_all(struct device *dev, struct device_node *np, + name[i] = '\0'; + tmp = regulator_get(dev, name); + if (IS_ERR(tmp)) { +- ret = -EINVAL; ++ ret = PTR_ERR(tmp); + goto error; + } + (*consumers)[n].consumer = tmp; +diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c +index 144c8e9a642e8b..448b9a5438e0b8 100644 +--- a/drivers/remoteproc/imx_rproc.c ++++ b/drivers/remoteproc/imx_rproc.c +@@ -210,7 +210,7 @@ static const struct imx_rproc_att imx_rproc_att_imx8mq[] = { + /* QSPI Code - alias */ + { 0x08000000, 0x08000000, 0x08000000, 0 }, + /* DDR (Code) - alias */ +- { 0x10000000, 0x80000000, 0x0FFE0000, 0 }, ++ { 0x10000000, 0x40000000, 0x0FFE0000, 0 }, + /* TCML */ + { 0x1FFE0000, 0x007E0000, 0x00020000, ATT_OWN | ATT_IOMEM}, + /* TCMU */ +@@ -1076,6 +1076,8 @@ static int imx_rproc_probe(struct platform_device *pdev) + return -ENOMEM; + } + ++ INIT_WORK(&priv->rproc_work, imx_rproc_vq_work); ++ + ret = imx_rproc_xtr_mbox_init(rproc); + if (ret) + goto err_put_wkq; +@@ -1094,8 +1096,6 @@ static int imx_rproc_probe(struct platform_device *pdev) + if (ret) + goto err_put_scu; + +- INIT_WORK(&priv->rproc_work, imx_rproc_vq_work); +- + if (rproc->state != RPROC_DETACHED) + rproc->auto_boot = of_property_read_bool(np, "fsl,auto-boot"); + +diff --git a/drivers/reset/reset-berlin.c b/drivers/reset/reset-berlin.c +index 2537ec05eceefd..578fe867080ce0 100644 +--- a/drivers/reset/reset-berlin.c ++++ b/drivers/reset/reset-berlin.c +@@ -68,13 +68,14 @@ static int berlin_reset_xlate(struct reset_controller_dev *rcdev, + + static int berlin2_reset_probe(struct platform_device *pdev) + { +- struct device_node *parent_np = of_get_parent(pdev->dev.of_node); ++ struct device_node *parent_np; + struct berlin_reset_priv *priv; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + ++ parent_np = of_get_parent(pdev->dev.of_node); + priv->regmap = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); + if (IS_ERR(priv->regmap)) +diff --git a/drivers/reset/reset-k210.c b/drivers/reset/reset-k210.c +index b62a2fd44e4e42..e77e4cca377dca 100644 +--- a/drivers/reset/reset-k210.c ++++ b/drivers/reset/reset-k210.c +@@ -90,7 +90,7 @@ static const struct reset_control_ops k210_rst_ops = { + static int k210_rst_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +- struct device_node *parent_np = of_get_parent(dev->of_node); ++ struct device_node *parent_np; + struct k210_rst *ksr; + + dev_info(dev, "K210 reset controller\n"); +@@ -99,6 +99,7 @@ static int k210_rst_probe(struct platform_device *pdev) + if (!ksr) + return -ENOMEM; + ++ parent_np = of_get_parent(dev->of_node); + ksr->map = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); + if (IS_ERR(ksr->map)) +diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c +index 99fadfb4cd9f26..09acc321d0133f 100644 +--- a/drivers/s390/crypto/ap_bus.c ++++ b/drivers/s390/crypto/ap_bus.c +@@ -107,6 +107,7 @@ debug_info_t *ap_dbf_info; + static bool ap_scan_bus(void); + static bool ap_scan_bus_result; /* result of last ap_scan_bus() */ + static DEFINE_MUTEX(ap_scan_bus_mutex); /* mutex ap_scan_bus() invocations */ ++static struct task_struct *ap_scan_bus_task; /* thread holding the scan mutex */ + static atomic64_t ap_scan_bus_count; /* counter ap_scan_bus() invocations */ + static int ap_scan_bus_time = AP_CONFIG_TIME; + static struct timer_list ap_scan_bus_timer; +@@ -1006,11 +1007,25 @@ bool ap_bus_force_rescan(void) + if (scan_counter <= 0) + goto out; + ++ /* ++ * There is one unlikely but nevertheless valid scenario where the ++ * thread holding the mutex may try to send some crypto load but ++ * all cards are offline so a rescan is triggered which causes ++ * a recursive call of ap_bus_force_rescan(). A simple return if ++ * the mutex is already locked by this thread solves this. ++ */ ++ if (mutex_is_locked(&ap_scan_bus_mutex)) { ++ if (ap_scan_bus_task == current) ++ goto out; ++ } ++ + /* Try to acquire the AP scan bus mutex */ + if (mutex_trylock(&ap_scan_bus_mutex)) { + /* mutex acquired, run the AP bus scan */ ++ ap_scan_bus_task = current; + ap_scan_bus_result = ap_scan_bus(); + rc = ap_scan_bus_result; ++ ap_scan_bus_task = NULL; + mutex_unlock(&ap_scan_bus_mutex); + goto out; + } +@@ -2284,7 +2299,9 @@ static void ap_scan_bus_wq_callback(struct work_struct *unused) + * system_long_wq which invokes this function here again. + */ + if (mutex_trylock(&ap_scan_bus_mutex)) { ++ ap_scan_bus_task = current; + ap_scan_bus_result = ap_scan_bus(); ++ ap_scan_bus_task = NULL; + mutex_unlock(&ap_scan_bus_mutex); + } + } +diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c +index cea3a79d538e4b..00e245173320c3 100644 +--- a/drivers/scsi/NCR5380.c ++++ b/drivers/scsi/NCR5380.c +@@ -1485,6 +1485,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, + unsigned char **data) + { + struct NCR5380_hostdata *hostdata = shost_priv(instance); ++ struct NCR5380_cmd *ncmd = NCR5380_to_ncmd(hostdata->connected); + int c = *count; + unsigned char p = *phase; + unsigned char *d = *data; +@@ -1496,7 +1497,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, + return -1; + } + +- NCR5380_to_ncmd(hostdata->connected)->phase = p; ++ ncmd->phase = p; + + if (p & SR_IO) { + if (hostdata->read_overruns) +@@ -1608,45 +1609,44 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, + * request. + */ + +- if (hostdata->flags & FLAG_DMA_FIXUP) { +- if (p & SR_IO) { +- /* +- * The workaround was to transfer fewer bytes than we +- * intended to with the pseudo-DMA read function, wait for +- * the chip to latch the last byte, read it, and then disable +- * pseudo-DMA mode. +- * +- * After REQ is asserted, the NCR5380 asserts DRQ and ACK. +- * REQ is deasserted when ACK is asserted, and not reasserted +- * until ACK goes false. Since the NCR5380 won't lower ACK +- * until DACK is asserted, which won't happen unless we twiddle +- * the DMA port or we take the NCR5380 out of DMA mode, we +- * can guarantee that we won't handshake another extra +- * byte. +- */ +- +- if (NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, +- BASR_DRQ, BASR_DRQ, 0) < 0) { +- result = -1; +- shost_printk(KERN_ERR, instance, "PDMA read: DRQ timeout\n"); +- } +- if (NCR5380_poll_politely(hostdata, STATUS_REG, +- SR_REQ, 0, 0) < 0) { +- result = -1; +- shost_printk(KERN_ERR, instance, "PDMA read: !REQ timeout\n"); +- } +- d[*count - 1] = NCR5380_read(INPUT_DATA_REG); +- } else { +- /* +- * Wait for the last byte to be sent. If REQ is being asserted for +- * the byte we're interested, we'll ACK it and it will go false. +- */ +- if (NCR5380_poll_politely2(hostdata, +- BUS_AND_STATUS_REG, BASR_DRQ, BASR_DRQ, +- BUS_AND_STATUS_REG, BASR_PHASE_MATCH, 0, 0) < 0) { +- result = -1; +- shost_printk(KERN_ERR, instance, "PDMA write: DRQ and phase timeout\n"); ++ if ((hostdata->flags & FLAG_DMA_FIXUP) && ++ (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) { ++ /* ++ * The workaround was to transfer fewer bytes than we ++ * intended to with the pseudo-DMA receive function, wait for ++ * the chip to latch the last byte, read it, and then disable ++ * DMA mode. ++ * ++ * After REQ is asserted, the NCR5380 asserts DRQ and ACK. ++ * REQ is deasserted when ACK is asserted, and not reasserted ++ * until ACK goes false. Since the NCR5380 won't lower ACK ++ * until DACK is asserted, which won't happen unless we twiddle ++ * the DMA port or we take the NCR5380 out of DMA mode, we ++ * can guarantee that we won't handshake another extra ++ * byte. ++ * ++ * If sending, wait for the last byte to be sent. If REQ is ++ * being asserted for the byte we're interested, we'll ACK it ++ * and it will go false. ++ */ ++ if (!NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, ++ BASR_DRQ, BASR_DRQ, 0)) { ++ if ((p & SR_IO) && ++ (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) { ++ if (!NCR5380_poll_politely(hostdata, STATUS_REG, ++ SR_REQ, 0, 0)) { ++ d[c] = NCR5380_read(INPUT_DATA_REG); ++ --ncmd->this_residual; ++ } else { ++ result = -1; ++ scmd_printk(KERN_ERR, hostdata->connected, ++ "PDMA fixup: !REQ timeout\n"); ++ } + } ++ } else if (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH) { ++ result = -1; ++ scmd_printk(KERN_ERR, hostdata->connected, ++ "PDMA fixup: DRQ timeout\n"); + } + } + +diff --git a/drivers/scsi/elx/libefc/efc_nport.c b/drivers/scsi/elx/libefc/efc_nport.c +index 2e83a667901fec..1a7437f4328e87 100644 +--- a/drivers/scsi/elx/libefc/efc_nport.c ++++ b/drivers/scsi/elx/libefc/efc_nport.c +@@ -705,9 +705,9 @@ efc_nport_vport_del(struct efc *efc, struct efc_domain *domain, + spin_lock_irqsave(&efc->lock, flags); + list_for_each_entry(nport, &domain->nport_list, list_entry) { + if (nport->wwpn == wwpn && nport->wwnn == wwnn) { +- kref_put(&nport->ref, nport->release); + /* Shutdown this NPORT */ + efc_sm_post_event(&nport->sm, EFC_EVT_SHUTDOWN, NULL); ++ kref_put(&nport->ref, nport->release); + break; + } + } +diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h +index 500253007b1dc8..26e1313ebb21fc 100644 +--- a/drivers/scsi/lpfc/lpfc_hw4.h ++++ b/drivers/scsi/lpfc/lpfc_hw4.h +@@ -4847,6 +4847,7 @@ struct fcp_iwrite64_wqe { + #define cmd_buff_len_SHIFT 16 + #define cmd_buff_len_MASK 0x00000ffff + #define cmd_buff_len_WORD word3 ++/* Note: payload_offset_len field depends on ASIC support */ + #define payload_offset_len_SHIFT 0 + #define payload_offset_len_MASK 0x0000ffff + #define payload_offset_len_WORD word3 +@@ -4863,6 +4864,7 @@ struct fcp_iread64_wqe { + #define cmd_buff_len_SHIFT 16 + #define cmd_buff_len_MASK 0x00000ffff + #define cmd_buff_len_WORD word3 ++/* Note: payload_offset_len field depends on ASIC support */ + #define payload_offset_len_SHIFT 0 + #define payload_offset_len_MASK 0x0000ffff + #define payload_offset_len_WORD word3 +@@ -4879,6 +4881,7 @@ struct fcp_icmnd64_wqe { + #define cmd_buff_len_SHIFT 16 + #define cmd_buff_len_MASK 0x00000ffff + #define cmd_buff_len_WORD word3 ++/* Note: payload_offset_len field depends on ASIC support */ + #define payload_offset_len_SHIFT 0 + #define payload_offset_len_MASK 0x0000ffff + #define payload_offset_len_WORD word3 +diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c +index e1dfa96c2a553a..0c1404dc5f3bdb 100644 +--- a/drivers/scsi/lpfc/lpfc_init.c ++++ b/drivers/scsi/lpfc/lpfc_init.c +@@ -4699,6 +4699,7 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev) + uint64_t wwn; + bool use_no_reset_hba = false; + int rc; ++ u8 if_type; + + if (lpfc_no_hba_reset_cnt) { + if (phba->sli_rev < LPFC_SLI_REV4 && +@@ -4773,10 +4774,24 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev) + shost->max_id = LPFC_MAX_TARGET; + shost->max_lun = vport->cfg_max_luns; + shost->this_id = -1; +- if (phba->sli_rev == LPFC_SLI_REV4) +- shost->max_cmd_len = LPFC_FCP_CDB_LEN_32; +- else ++ ++ /* Set max_cmd_len applicable to ASIC support */ ++ if (phba->sli_rev == LPFC_SLI_REV4) { ++ if_type = bf_get(lpfc_sli_intf_if_type, ++ &phba->sli4_hba.sli_intf); ++ switch (if_type) { ++ case LPFC_SLI_INTF_IF_TYPE_2: ++ fallthrough; ++ case LPFC_SLI_INTF_IF_TYPE_6: ++ shost->max_cmd_len = LPFC_FCP_CDB_LEN_32; ++ break; ++ default: ++ shost->max_cmd_len = LPFC_FCP_CDB_LEN; ++ break; ++ } ++ } else { + shost->max_cmd_len = LPFC_FCP_CDB_LEN; ++ } + + if (phba->sli_rev == LPFC_SLI_REV4) { + if (!phba->cfg_fcp_mq_threshold || +diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c +index 98ce9d97a22570..9f0b59672e1915 100644 +--- a/drivers/scsi/lpfc/lpfc_scsi.c ++++ b/drivers/scsi/lpfc/lpfc_scsi.c +@@ -4760,7 +4760,7 @@ static int lpfc_scsi_prep_cmnd_buf_s4(struct lpfc_vport *vport, + + /* Word 3 */ + bf_set(payload_offset_len, &wqe->fcp_icmd, +- sizeof(struct fcp_cmnd32) + sizeof(struct fcp_rsp)); ++ sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp)); + + /* Word 6 */ + bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com, +diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c +index a402c4dc4645d3..2e9fad1e3069ec 100644 +--- a/drivers/scsi/mac_scsi.c ++++ b/drivers/scsi/mac_scsi.c +@@ -102,11 +102,15 @@ __setup("mac5380=", mac_scsi_setup); + * Linux SCSI drivers lack knowledge of the timing behaviour of SCSI targets + * so bus errors are unavoidable. + * +- * If a MOVE.B instruction faults, we assume that zero bytes were transferred +- * and simply retry. That assumption probably depends on target behaviour but +- * seems to hold up okay. The NOP provides synchronization: without it the +- * fault can sometimes occur after the program counter has moved past the +- * offending instruction. Post-increment addressing can't be used. ++ * If a MOVE.B instruction faults during a receive operation, we assume the ++ * target sent nothing and try again. That assumption probably depends on ++ * target firmware but it seems to hold up okay. If a fault happens during a ++ * send operation, the target may or may not have seen /ACK and got the byte. ++ * It's uncertain so the whole SCSI command gets retried. ++ * ++ * The NOP is needed for synchronization because the fault address in the ++ * exception stack frame may or may not be the instruction that actually ++ * caused the bus error. Post-increment addressing can't be used. + */ + + #define MOVE_BYTE(operands) \ +@@ -208,8 +212,6 @@ __setup("mac5380=", mac_scsi_setup); + ".previous \n" \ + : "+a" (addr), "+r" (n), "+r" (result) : "a" (io)) + +-#define MAC_PDMA_DELAY 32 +- + static inline int mac_pdma_recv(void __iomem *io, unsigned char *start, int n) + { + unsigned char *addr = start; +@@ -245,22 +247,21 @@ static inline int mac_pdma_send(unsigned char *start, void __iomem *io, int n) + if (n >= 1) { + MOVE_BYTE("%0@,%3@"); + if (result) +- goto out; ++ return -1; + } + if (n >= 1 && ((unsigned long)addr & 1)) { + MOVE_BYTE("%0@,%3@"); + if (result) +- goto out; ++ return -2; + } + while (n >= 32) + MOVE_16_WORDS("%0@+,%3@"); + while (n >= 2) + MOVE_WORD("%0@+,%3@"); + if (result) +- return start - addr; /* Negated to indicate uncertain length */ ++ return start - addr - 1; /* Negated to indicate uncertain length */ + if (n == 1) + MOVE_BYTE("%0@,%3@"); +-out: + return addr - start; + } + +@@ -274,25 +275,56 @@ static inline void write_ctrl_reg(struct NCR5380_hostdata *hostdata, u32 value) + out_be32(hostdata->io + (CTRL_REG << 4), value); + } + ++static inline int macscsi_wait_for_drq(struct NCR5380_hostdata *hostdata) ++{ ++ unsigned int n = 1; /* effectively multiplies NCR5380_REG_POLL_TIME */ ++ unsigned char basr; ++ ++again: ++ basr = NCR5380_read(BUS_AND_STATUS_REG); ++ ++ if (!(basr & BASR_PHASE_MATCH)) ++ return 1; ++ ++ if (basr & BASR_IRQ) ++ return -1; ++ ++ if (basr & BASR_DRQ) ++ return 0; ++ ++ if (n-- == 0) { ++ NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); ++ dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host, ++ "%s: DRQ timeout\n", __func__); ++ return -1; ++ } ++ ++ NCR5380_poll_politely2(hostdata, ++ BUS_AND_STATUS_REG, BASR_DRQ, BASR_DRQ, ++ BUS_AND_STATUS_REG, BASR_PHASE_MATCH, 0, 0); ++ goto again; ++} ++ + static inline int macscsi_pread(struct NCR5380_hostdata *hostdata, + unsigned char *dst, int len) + { + u8 __iomem *s = hostdata->pdma_io + (INPUT_DATA_REG << 4); + unsigned char *d = dst; +- int result = 0; + + hostdata->pdma_residual = len; + +- while (!NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, +- BASR_DRQ | BASR_PHASE_MATCH, +- BASR_DRQ | BASR_PHASE_MATCH, 0)) { +- int bytes; ++ while (macscsi_wait_for_drq(hostdata) == 0) { ++ int bytes, chunk_bytes; + + if (macintosh_config->ident == MAC_MODEL_IIFX) + write_ctrl_reg(hostdata, CTRL_HANDSHAKE_MODE | + CTRL_INTERRUPTS_ENABLE); + +- bytes = mac_pdma_recv(s, d, min(hostdata->pdma_residual, 512)); ++ chunk_bytes = min(hostdata->pdma_residual, 512); ++ bytes = mac_pdma_recv(s, d, chunk_bytes); ++ ++ if (macintosh_config->ident == MAC_MODEL_IIFX) ++ write_ctrl_reg(hostdata, CTRL_INTERRUPTS_ENABLE); + + if (bytes > 0) { + d += bytes; +@@ -300,37 +332,25 @@ static inline int macscsi_pread(struct NCR5380_hostdata *hostdata, + } + + if (hostdata->pdma_residual == 0) +- goto out; ++ break; + +- if (NCR5380_poll_politely2(hostdata, STATUS_REG, SR_REQ, SR_REQ, +- BUS_AND_STATUS_REG, BASR_ACK, +- BASR_ACK, 0) < 0) +- scmd_printk(KERN_DEBUG, hostdata->connected, +- "%s: !REQ and !ACK\n", __func__); +- if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) +- goto out; ++ if (bytes > 0) ++ continue; + +- if (bytes == 0) +- udelay(MAC_PDMA_DELAY); ++ NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); ++ dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host, ++ "%s: bus error [%d/%d] (%d/%d)\n", ++ __func__, d - dst, len, bytes, chunk_bytes); + +- if (bytes >= 0) ++ if (bytes == 0) + continue; + +- dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host, +- "%s: bus error (%d/%d)\n", __func__, d - dst, len); +- NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); +- result = -1; +- goto out; ++ if (macscsi_wait_for_drq(hostdata) <= 0) ++ set_host_byte(hostdata->connected, DID_ERROR); ++ break; + } + +- scmd_printk(KERN_ERR, hostdata->connected, +- "%s: phase mismatch or !DRQ\n", __func__); +- NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); +- result = -1; +-out: +- if (macintosh_config->ident == MAC_MODEL_IIFX) +- write_ctrl_reg(hostdata, CTRL_INTERRUPTS_ENABLE); +- return result; ++ return 0; + } + + static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata, +@@ -338,67 +358,47 @@ static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata, + { + unsigned char *s = src; + u8 __iomem *d = hostdata->pdma_io + (OUTPUT_DATA_REG << 4); +- int result = 0; + + hostdata->pdma_residual = len; + +- while (!NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, +- BASR_DRQ | BASR_PHASE_MATCH, +- BASR_DRQ | BASR_PHASE_MATCH, 0)) { +- int bytes; ++ while (macscsi_wait_for_drq(hostdata) == 0) { ++ int bytes, chunk_bytes; + + if (macintosh_config->ident == MAC_MODEL_IIFX) + write_ctrl_reg(hostdata, CTRL_HANDSHAKE_MODE | + CTRL_INTERRUPTS_ENABLE); + +- bytes = mac_pdma_send(s, d, min(hostdata->pdma_residual, 512)); ++ chunk_bytes = min(hostdata->pdma_residual, 512); ++ bytes = mac_pdma_send(s, d, chunk_bytes); ++ ++ if (macintosh_config->ident == MAC_MODEL_IIFX) ++ write_ctrl_reg(hostdata, CTRL_INTERRUPTS_ENABLE); + + if (bytes > 0) { + s += bytes; + hostdata->pdma_residual -= bytes; + } + +- if (hostdata->pdma_residual == 0) { +- if (NCR5380_poll_politely(hostdata, TARGET_COMMAND_REG, +- TCR_LAST_BYTE_SENT, +- TCR_LAST_BYTE_SENT, +- 0) < 0) { +- scmd_printk(KERN_ERR, hostdata->connected, +- "%s: Last Byte Sent timeout\n", __func__); +- result = -1; +- } +- goto out; +- } ++ if (hostdata->pdma_residual == 0) ++ break; + +- if (NCR5380_poll_politely2(hostdata, STATUS_REG, SR_REQ, SR_REQ, +- BUS_AND_STATUS_REG, BASR_ACK, +- BASR_ACK, 0) < 0) +- scmd_printk(KERN_DEBUG, hostdata->connected, +- "%s: !REQ and !ACK\n", __func__); +- if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) +- goto out; ++ if (bytes > 0) ++ continue; + +- if (bytes == 0) +- udelay(MAC_PDMA_DELAY); ++ NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); ++ dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host, ++ "%s: bus error [%d/%d] (%d/%d)\n", ++ __func__, s - src, len, bytes, chunk_bytes); + +- if (bytes >= 0) ++ if (bytes == 0) + continue; + +- dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host, +- "%s: bus error (%d/%d)\n", __func__, s - src, len); +- NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); +- result = -1; +- goto out; ++ if (macscsi_wait_for_drq(hostdata) <= 0) ++ set_host_byte(hostdata->connected, DID_ERROR); ++ break; + } + +- scmd_printk(KERN_ERR, hostdata->connected, +- "%s: phase mismatch or !DRQ\n", __func__); +- NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); +- result = -1; +-out: +- if (macintosh_config->ident == MAC_MODEL_IIFX) +- write_ctrl_reg(hostdata, CTRL_INTERRUPTS_ENABLE); +- return result; ++ return 0; + } + + static int macscsi_dma_xfer_len(struct NCR5380_hostdata *hostdata, +diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c +index 7d2a294ebc3d79..5dd100175ec616 100644 +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -3283,7 +3283,7 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp) + rcu_read_lock(); + vpd = rcu_dereference(sdkp->device->vpd_pgb1); + +- if (!vpd || vpd->len < 8) { ++ if (!vpd || vpd->len <= 8) { + rcu_read_unlock(); + return; + } +diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c +index 24c7cb285dca0f..c1524fb334eb5c 100644 +--- a/drivers/scsi/smartpqi/smartpqi_init.c ++++ b/drivers/scsi/smartpqi/smartpqi_init.c +@@ -2354,14 +2354,6 @@ static inline void pqi_mask_device(u8 *scsi3addr) + scsi3addr[3] |= 0xc0; + } + +-static inline bool pqi_is_multipath_device(struct pqi_scsi_dev *device) +-{ +- if (pqi_is_logical_device(device)) +- return false; +- +- return (device->path_map & (device->path_map - 1)) != 0; +-} +- + static inline bool pqi_expose_device(struct pqi_scsi_dev *device) + { + return !device->is_physical_device || !pqi_skip_device(device->scsi3addr); +@@ -3258,14 +3250,12 @@ static void pqi_process_aio_io_error(struct pqi_io_request *io_request) + int residual_count; + int xfer_count; + bool device_offline; +- struct pqi_scsi_dev *device; + + scmd = io_request->scmd; + error_info = io_request->error_info; + host_byte = DID_OK; + sense_data_length = 0; + device_offline = false; +- device = scmd->device->hostdata; + + switch (error_info->service_response) { + case PQI_AIO_SERV_RESPONSE_COMPLETE: +@@ -3290,14 +3280,8 @@ static void pqi_process_aio_io_error(struct pqi_io_request *io_request) + break; + case PQI_AIO_STATUS_AIO_PATH_DISABLED: + pqi_aio_path_disabled(io_request); +- if (pqi_is_multipath_device(device)) { +- pqi_device_remove_start(device); +- host_byte = DID_NO_CONNECT; +- scsi_status = SAM_STAT_CHECK_CONDITION; +- } else { +- scsi_status = SAM_STAT_GOOD; +- io_request->status = -EAGAIN; +- } ++ scsi_status = SAM_STAT_GOOD; ++ io_request->status = -EAGAIN; + break; + case PQI_AIO_STATUS_NO_PATH_TO_DEVICE: + case PQI_AIO_STATUS_INVALID_DEVICE: +diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c +index f498db9abe35f0..04035706b96dc8 100644 +--- a/drivers/soc/fsl/qe/qmc.c ++++ b/drivers/soc/fsl/qe/qmc.c +@@ -940,11 +940,13 @@ static int qmc_chan_start_rx(struct qmc_chan *chan) + goto end; + } + +- ret = qmc_setup_chan_trnsync(chan->qmc, chan); +- if (ret) { +- dev_err(chan->qmc->dev, "chan %u: setup TRNSYNC failed (%d)\n", +- chan->id, ret); +- goto end; ++ if (chan->mode == QMC_TRANSPARENT) { ++ ret = qmc_setup_chan_trnsync(chan->qmc, chan); ++ if (ret) { ++ dev_err(chan->qmc->dev, "chan %u: setup TRNSYNC failed (%d)\n", ++ chan->id, ret); ++ goto end; ++ } + } + + /* Restart the receiver */ +@@ -982,11 +984,13 @@ static int qmc_chan_start_tx(struct qmc_chan *chan) + goto end; + } + +- ret = qmc_setup_chan_trnsync(chan->qmc, chan); +- if (ret) { +- dev_err(chan->qmc->dev, "chan %u: setup TRNSYNC failed (%d)\n", +- chan->id, ret); +- goto end; ++ if (chan->mode == QMC_TRANSPARENT) { ++ ret = qmc_setup_chan_trnsync(chan->qmc, chan); ++ if (ret) { ++ dev_err(chan->qmc->dev, "chan %u: setup TRNSYNC failed (%d)\n", ++ chan->id, ret); ++ goto end; ++ } + } + + /* +diff --git a/drivers/soc/fsl/qe/tsa.c b/drivers/soc/fsl/qe/tsa.c +index 6c5741cf5e9d2a..53968ea84c8872 100644 +--- a/drivers/soc/fsl/qe/tsa.c ++++ b/drivers/soc/fsl/qe/tsa.c +@@ -140,7 +140,7 @@ static inline void tsa_write32(void __iomem *addr, u32 val) + iowrite32be(val, addr); + } + +-static inline void tsa_write8(void __iomem *addr, u32 val) ++static inline void tsa_write8(void __iomem *addr, u8 val) + { + iowrite8(val, addr); + } +diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c +index b7056aed4c7d10..9d64283d212549 100644 +--- a/drivers/soc/qcom/smd-rpm.c ++++ b/drivers/soc/qcom/smd-rpm.c +@@ -196,9 +196,6 @@ static int qcom_smd_rpm_probe(struct rpmsg_device *rpdev) + { + struct qcom_smd_rpm *rpm; + +- if (!rpdev->dev.of_node) +- return -EINVAL; +- + rpm = devm_kzalloc(&rpdev->dev, sizeof(*rpm), GFP_KERNEL); + if (!rpm) + return -ENOMEM; +@@ -218,18 +215,38 @@ static void qcom_smd_rpm_remove(struct rpmsg_device *rpdev) + of_platform_depopulate(&rpdev->dev); + } + +-static const struct rpmsg_device_id qcom_smd_rpm_id_table[] = { +- { .name = "rpm_requests", }, +- { /* sentinel */ } ++static const struct of_device_id qcom_smd_rpm_of_match[] = { ++ { .compatible = "qcom,rpm-apq8084" }, ++ { .compatible = "qcom,rpm-ipq6018" }, ++ { .compatible = "qcom,rpm-ipq9574" }, ++ { .compatible = "qcom,rpm-msm8226" }, ++ { .compatible = "qcom,rpm-msm8909" }, ++ { .compatible = "qcom,rpm-msm8916" }, ++ { .compatible = "qcom,rpm-msm8936" }, ++ { .compatible = "qcom,rpm-msm8953" }, ++ { .compatible = "qcom,rpm-msm8974" }, ++ { .compatible = "qcom,rpm-msm8976" }, ++ { .compatible = "qcom,rpm-msm8994" }, ++ { .compatible = "qcom,rpm-msm8996" }, ++ { .compatible = "qcom,rpm-msm8998" }, ++ { .compatible = "qcom,rpm-sdm660" }, ++ { .compatible = "qcom,rpm-sm6115" }, ++ { .compatible = "qcom,rpm-sm6125" }, ++ { .compatible = "qcom,rpm-sm6375" }, ++ { .compatible = "qcom,rpm-qcm2290" }, ++ { .compatible = "qcom,rpm-qcs404" }, ++ {} + }; +-MODULE_DEVICE_TABLE(rpmsg, qcom_smd_rpm_id_table); ++MODULE_DEVICE_TABLE(of, qcom_smd_rpm_of_match); + + static struct rpmsg_driver qcom_smd_rpm_driver = { + .probe = qcom_smd_rpm_probe, + .remove = qcom_smd_rpm_remove, + .callback = qcom_smd_rpm_callback, +- .id_table = qcom_smd_rpm_id_table, +- .drv.name = "qcom_smd_rpm", ++ .drv = { ++ .name = "qcom_smd_rpm", ++ .of_match_table = qcom_smd_rpm_of_match, ++ }, + }; + + static int __init qcom_smd_rpm_init(void) +diff --git a/drivers/soc/versatile/soc-integrator.c b/drivers/soc/versatile/soc-integrator.c +index bab4ad87aa7500..d5099a3386b4fc 100644 +--- a/drivers/soc/versatile/soc-integrator.c ++++ b/drivers/soc/versatile/soc-integrator.c +@@ -113,6 +113,7 @@ static int __init integrator_soc_init(void) + return -ENODEV; + + syscon_regmap = syscon_node_to_regmap(np); ++ of_node_put(np); + if (IS_ERR(syscon_regmap)) + return PTR_ERR(syscon_regmap); + +diff --git a/drivers/soc/versatile/soc-realview.c b/drivers/soc/versatile/soc-realview.c +index c6876d232d8fd6..cf91abe07d38d0 100644 +--- a/drivers/soc/versatile/soc-realview.c ++++ b/drivers/soc/versatile/soc-realview.c +@@ -4,6 +4,7 @@ + * + * Author: Linus Walleij <linus.walleij@linaro.org> + */ ++#include <linux/device.h> + #include <linux/init.h> + #include <linux/io.h> + #include <linux/slab.h> +@@ -81,6 +82,13 @@ static struct attribute *realview_attrs[] = { + + ATTRIBUTE_GROUPS(realview); + ++static void realview_soc_socdev_release(void *data) ++{ ++ struct soc_device *soc_dev = data; ++ ++ soc_device_unregister(soc_dev); ++} ++ + static int realview_soc_probe(struct platform_device *pdev) + { + struct regmap *syscon_regmap; +@@ -93,7 +101,7 @@ static int realview_soc_probe(struct platform_device *pdev) + if (IS_ERR(syscon_regmap)) + return PTR_ERR(syscon_regmap); + +- soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); ++ soc_dev_attr = devm_kzalloc(&pdev->dev, sizeof(*soc_dev_attr), GFP_KERNEL); + if (!soc_dev_attr) + return -ENOMEM; + +@@ -106,10 +114,14 @@ static int realview_soc_probe(struct platform_device *pdev) + soc_dev_attr->family = "Versatile"; + soc_dev_attr->custom_attr_group = realview_groups[0]; + soc_dev = soc_device_register(soc_dev_attr); +- if (IS_ERR(soc_dev)) { +- kfree(soc_dev_attr); ++ if (IS_ERR(soc_dev)) + return -ENODEV; +- } ++ ++ ret = devm_add_action_or_reset(&pdev->dev, realview_soc_socdev_release, ++ soc_dev); ++ if (ret) ++ return ret; ++ + ret = regmap_read(syscon_regmap, REALVIEW_SYS_ID_OFFSET, + &realview_coreid); + if (ret) +diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c +index 5aaff3bee1b78f..9ea91432c11d81 100644 +--- a/drivers/spi/atmel-quadspi.c ++++ b/drivers/spi/atmel-quadspi.c +@@ -375,9 +375,9 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq, + * If the QSPI controller is set in regular SPI mode, set it in + * Serial Memory Mode (SMM). + */ +- if (aq->mr != QSPI_MR_SMM) { +- atmel_qspi_write(QSPI_MR_SMM, aq, QSPI_MR); +- aq->mr = QSPI_MR_SMM; ++ if (!(aq->mr & QSPI_MR_SMM)) { ++ aq->mr |= QSPI_MR_SMM; ++ atmel_qspi_write(aq->mr, aq, QSPI_MR); + } + + /* Clear pending interrupts */ +@@ -501,7 +501,8 @@ static int atmel_qspi_setup(struct spi_device *spi) + if (ret < 0) + return ret; + +- aq->scr = QSPI_SCR_SCBR(scbr); ++ aq->scr &= ~QSPI_SCR_SCBR_MASK; ++ aq->scr |= QSPI_SCR_SCBR(scbr); + atmel_qspi_write(aq->scr, aq, QSPI_SCR); + + pm_runtime_mark_last_busy(ctrl->dev.parent); +@@ -534,6 +535,7 @@ static int atmel_qspi_set_cs_timing(struct spi_device *spi) + if (ret < 0) + return ret; + ++ aq->scr &= ~QSPI_SCR_DLYBS_MASK; + aq->scr |= QSPI_SCR_DLYBS(cs_setup); + atmel_qspi_write(aq->scr, aq, QSPI_SCR); + +@@ -549,8 +551,8 @@ static void atmel_qspi_init(struct atmel_qspi *aq) + atmel_qspi_write(QSPI_CR_SWRST, aq, QSPI_CR); + + /* Set the QSPI controller by default in Serial Memory Mode */ +- atmel_qspi_write(QSPI_MR_SMM, aq, QSPI_MR); +- aq->mr = QSPI_MR_SMM; ++ aq->mr |= QSPI_MR_SMM; ++ atmel_qspi_write(aq->mr, aq, QSPI_MR); + + /* Enable the QSPI controller */ + atmel_qspi_write(QSPI_CR_QSPIEN, aq, QSPI_CR); +@@ -726,6 +728,7 @@ static void atmel_qspi_remove(struct platform_device *pdev) + clk_unprepare(aq->pclk); + + pm_runtime_disable(&pdev->dev); ++ pm_runtime_dont_use_autosuspend(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); + } + +diff --git a/drivers/spi/spi-airoha-snfi.c b/drivers/spi/spi-airoha-snfi.c +index 9d97ec98881cc9..94458df53eae23 100644 +--- a/drivers/spi/spi-airoha-snfi.c ++++ b/drivers/spi/spi-airoha-snfi.c +@@ -211,9 +211,6 @@ struct airoha_snand_dev { + + u8 *txrx_buf; + dma_addr_t dma_addr; +- +- u64 cur_page_num; +- bool data_need_update; + }; + + struct airoha_snand_ctrl { +@@ -405,7 +402,7 @@ static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd, + for (i = 0; i < len; i += data_len) { + int err; + +- data_len = min(len, SPI_MAX_TRANSFER_SIZE); ++ data_len = min(len - i, SPI_MAX_TRANSFER_SIZE); + err = airoha_snand_set_fifo_op(as_ctrl, cmd, data_len); + if (err) + return err; +@@ -427,7 +424,7 @@ static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl, u8 *data, + for (i = 0; i < len; i += data_len) { + int err; + +- data_len = min(len, SPI_MAX_TRANSFER_SIZE); ++ data_len = min(len - i, SPI_MAX_TRANSFER_SIZE); + err = airoha_snand_set_fifo_op(as_ctrl, 0xc, data_len); + if (err) + return err; +@@ -644,11 +641,6 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc, + u32 val, rd_mode; + int err; + +- if (!as_dev->data_need_update) +- return len; +- +- as_dev->data_need_update = false; +- + switch (op->cmd.opcode) { + case SPI_NAND_OP_READ_FROM_CACHE_DUAL: + rd_mode = 1; +@@ -739,8 +731,13 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc, + if (err) + return err; + +- err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_STA_CTL1, +- SPI_NFI_READ_FROM_CACHE_DONE); ++ /* ++ * SPI_NFI_READ_FROM_CACHE_DONE bit must be written at the end ++ * of dirmap_read operation even if it is already set. ++ */ ++ err = regmap_write_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_STA_CTL1, ++ SPI_NFI_READ_FROM_CACHE_DONE, ++ SPI_NFI_READ_FROM_CACHE_DONE); + if (err) + return err; + +@@ -870,8 +867,13 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc, + if (err) + return err; + +- err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_STA_CTL1, +- SPI_NFI_LOAD_TO_CACHE_DONE); ++ /* ++ * SPI_NFI_LOAD_TO_CACHE_DONE bit must be written at the end ++ * of dirmap_write operation even if it is already set. ++ */ ++ err = regmap_write_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_STA_CTL1, ++ SPI_NFI_LOAD_TO_CACHE_DONE, ++ SPI_NFI_LOAD_TO_CACHE_DONE); + if (err) + return err; + +@@ -885,23 +887,11 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc, + static int airoha_snand_exec_op(struct spi_mem *mem, + const struct spi_mem_op *op) + { +- struct airoha_snand_dev *as_dev = spi_get_ctldata(mem->spi); + u8 data[8], cmd, opcode = op->cmd.opcode; + struct airoha_snand_ctrl *as_ctrl; + int i, err; + + as_ctrl = spi_controller_get_devdata(mem->spi->controller); +- if (opcode == SPI_NAND_OP_PROGRAM_EXECUTE && +- op->addr.val == as_dev->cur_page_num) { +- as_dev->data_need_update = true; +- } else if (opcode == SPI_NAND_OP_PAGE_READ) { +- if (!as_dev->data_need_update && +- op->addr.val == as_dev->cur_page_num) +- return 0; +- +- as_dev->data_need_update = true; +- as_dev->cur_page_num = op->addr.val; +- } + + /* switch to manual mode */ + err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL); +@@ -986,7 +976,6 @@ static int airoha_snand_setup(struct spi_device *spi) + if (dma_mapping_error(as_ctrl->dev, as_dev->dma_addr)) + return -ENOMEM; + +- as_dev->data_need_update = true; + spi_set_ctldata(spi, as_dev); + + return 0; +diff --git a/drivers/spi/spi-bcmbca-hsspi.c b/drivers/spi/spi-bcmbca-hsspi.c +index 9f64afd8164ea9..4965bc86d7f52a 100644 +--- a/drivers/spi/spi-bcmbca-hsspi.c ++++ b/drivers/spi/spi-bcmbca-hsspi.c +@@ -546,12 +546,14 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev) + goto out_put_host; + } + +- pm_runtime_enable(&pdev->dev); ++ ret = devm_pm_runtime_enable(&pdev->dev); ++ if (ret) ++ goto out_put_host; + + ret = sysfs_create_group(&pdev->dev.kobj, &bcmbca_hsspi_group); + if (ret) { + dev_err(&pdev->dev, "couldn't register sysfs group\n"); +- goto out_pm_disable; ++ goto out_put_host; + } + + /* register and we are done */ +@@ -565,8 +567,6 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev) + + out_sysgroup_disable: + sysfs_remove_group(&pdev->dev.kobj, &bcmbca_hsspi_group); +-out_pm_disable: +- pm_runtime_disable(&pdev->dev); + out_put_host: + spi_controller_put(host); + out_disable_pll_clk: +diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c +index d2f603e1014cf5..e235df4177f965 100644 +--- a/drivers/spi/spi-fsl-lpspi.c ++++ b/drivers/spi/spi-fsl-lpspi.c +@@ -986,6 +986,7 @@ static void fsl_lpspi_remove(struct platform_device *pdev) + + fsl_lpspi_dma_exit(controller); + ++ pm_runtime_dont_use_autosuspend(fsl_lpspi->dev); + pm_runtime_disable(fsl_lpspi->dev); + } + +diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c +index 6585b19a48662d..a961785724cdf2 100644 +--- a/drivers/spi/spi-nxp-fspi.c ++++ b/drivers/spi/spi-nxp-fspi.c +@@ -57,13 +57,6 @@ + #include <linux/spi/spi.h> + #include <linux/spi/spi-mem.h> + +-/* +- * The driver only uses one single LUT entry, that is updated on +- * each call of exec_op(). Index 0 is preset at boot with a basic +- * read operation, so let's use the last entry (31). +- */ +-#define SEQID_LUT 31 +- + /* Registers used by the driver */ + #define FSPI_MCR0 0x00 + #define FSPI_MCR0_AHB_TIMEOUT(x) ((x) << 24) +@@ -263,9 +256,6 @@ + #define FSPI_TFDR 0x180 + + #define FSPI_LUT_BASE 0x200 +-#define FSPI_LUT_OFFSET (SEQID_LUT * 4 * 4) +-#define FSPI_LUT_REG(idx) \ +- (FSPI_LUT_BASE + FSPI_LUT_OFFSET + (idx) * 4) + + /* register map end */ + +@@ -341,6 +331,7 @@ struct nxp_fspi_devtype_data { + unsigned int txfifo; + unsigned int ahb_buf_size; + unsigned int quirks; ++ unsigned int lut_num; + bool little_endian; + }; + +@@ -349,6 +340,7 @@ static struct nxp_fspi_devtype_data lx2160a_data = { + .txfifo = SZ_1K, /* (128 * 64 bits) */ + .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ + .quirks = 0, ++ .lut_num = 32, + .little_endian = true, /* little-endian */ + }; + +@@ -357,6 +349,7 @@ static struct nxp_fspi_devtype_data imx8mm_data = { + .txfifo = SZ_1K, /* (128 * 64 bits) */ + .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ + .quirks = 0, ++ .lut_num = 32, + .little_endian = true, /* little-endian */ + }; + +@@ -365,6 +358,7 @@ static struct nxp_fspi_devtype_data imx8qxp_data = { + .txfifo = SZ_1K, /* (128 * 64 bits) */ + .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ + .quirks = 0, ++ .lut_num = 32, + .little_endian = true, /* little-endian */ + }; + +@@ -373,6 +367,16 @@ static struct nxp_fspi_devtype_data imx8dxl_data = { + .txfifo = SZ_1K, /* (128 * 64 bits) */ + .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ + .quirks = FSPI_QUIRK_USE_IP_ONLY, ++ .lut_num = 32, ++ .little_endian = true, /* little-endian */ ++}; ++ ++static struct nxp_fspi_devtype_data imx8ulp_data = { ++ .rxfifo = SZ_512, /* (64 * 64 bits) */ ++ .txfifo = SZ_1K, /* (128 * 64 bits) */ ++ .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ ++ .quirks = 0, ++ .lut_num = 16, + .little_endian = true, /* little-endian */ + }; + +@@ -544,6 +548,8 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f, + void __iomem *base = f->iobase; + u32 lutval[4] = {}; + int lutidx = 1, i; ++ u32 lut_offset = (f->devtype_data->lut_num - 1) * 4 * 4; ++ u32 target_lut_reg; + + /* cmd */ + lutval[0] |= LUT_DEF(0, LUT_CMD, LUT_PAD(op->cmd.buswidth), +@@ -588,8 +594,10 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f, + fspi_writel(f, FSPI_LCKER_UNLOCK, f->iobase + FSPI_LCKCR); + + /* fill LUT */ +- for (i = 0; i < ARRAY_SIZE(lutval); i++) +- fspi_writel(f, lutval[i], base + FSPI_LUT_REG(i)); ++ for (i = 0; i < ARRAY_SIZE(lutval); i++) { ++ target_lut_reg = FSPI_LUT_BASE + lut_offset + i * 4; ++ fspi_writel(f, lutval[i], base + target_lut_reg); ++ } + + dev_dbg(f->dev, "CMD[%02x] lutval[0:%08x 1:%08x 2:%08x 3:%08x], size: 0x%08x\n", + op->cmd.opcode, lutval[0], lutval[1], lutval[2], lutval[3], op->data.nbytes); +@@ -876,7 +884,7 @@ static int nxp_fspi_do_op(struct nxp_fspi *f, const struct spi_mem_op *op) + void __iomem *base = f->iobase; + int seqnum = 0; + int err = 0; +- u32 reg; ++ u32 reg, seqid_lut; + + reg = fspi_readl(f, base + FSPI_IPRXFCR); + /* invalid RXFIFO first */ +@@ -892,8 +900,9 @@ static int nxp_fspi_do_op(struct nxp_fspi *f, const struct spi_mem_op *op) + * the LUT at each exec_op() call. And also specify the DATA + * length, since it's has not been specified in the LUT. + */ ++ seqid_lut = f->devtype_data->lut_num - 1; + fspi_writel(f, op->data.nbytes | +- (SEQID_LUT << FSPI_IPCR1_SEQID_SHIFT) | ++ (seqid_lut << FSPI_IPCR1_SEQID_SHIFT) | + (seqnum << FSPI_IPCR1_SEQNUM_SHIFT), + base + FSPI_IPCR1); + +@@ -1017,7 +1026,7 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f) + { + void __iomem *base = f->iobase; + int ret, i; +- u32 reg; ++ u32 reg, seqid_lut; + + /* disable and unprepare clock to avoid glitch pass to controller */ + nxp_fspi_clk_disable_unprep(f); +@@ -1092,11 +1101,17 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f) + fspi_writel(f, reg, base + FSPI_FLSHB1CR1); + fspi_writel(f, reg, base + FSPI_FLSHB2CR1); + ++ /* ++ * The driver only uses one single LUT entry, that is updated on ++ * each call of exec_op(). Index 0 is preset at boot with a basic ++ * read operation, so let's use the last entry. ++ */ ++ seqid_lut = f->devtype_data->lut_num - 1; + /* AHB Read - Set lut sequence ID for all CS. */ +- fspi_writel(f, SEQID_LUT, base + FSPI_FLSHA1CR2); +- fspi_writel(f, SEQID_LUT, base + FSPI_FLSHA2CR2); +- fspi_writel(f, SEQID_LUT, base + FSPI_FLSHB1CR2); +- fspi_writel(f, SEQID_LUT, base + FSPI_FLSHB2CR2); ++ fspi_writel(f, seqid_lut, base + FSPI_FLSHA1CR2); ++ fspi_writel(f, seqid_lut, base + FSPI_FLSHA2CR2); ++ fspi_writel(f, seqid_lut, base + FSPI_FLSHB1CR2); ++ fspi_writel(f, seqid_lut, base + FSPI_FLSHB2CR2); + + f->selected = -1; + +@@ -1291,6 +1306,7 @@ static const struct of_device_id nxp_fspi_dt_ids[] = { + { .compatible = "nxp,imx8mp-fspi", .data = (void *)&imx8mm_data, }, + { .compatible = "nxp,imx8qxp-fspi", .data = (void *)&imx8qxp_data, }, + { .compatible = "nxp,imx8dxl-fspi", .data = (void *)&imx8dxl_data, }, ++ { .compatible = "nxp,imx8ulp-fspi", .data = (void *)&imx8ulp_data, }, + { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(of, nxp_fspi_dt_ids); +diff --git a/drivers/spi/spi-ppc4xx.c b/drivers/spi/spi-ppc4xx.c +index 942c3117ab3a90..8f6309f32de0b5 100644 +--- a/drivers/spi/spi-ppc4xx.c ++++ b/drivers/spi/spi-ppc4xx.c +@@ -27,7 +27,6 @@ + #include <linux/wait.h> + #include <linux/platform_device.h> + #include <linux/of_address.h> +-#include <linux/of_irq.h> + #include <linux/of_platform.h> + #include <linux/interrupt.h> + #include <linux/delay.h> +@@ -412,7 +411,11 @@ static int spi_ppc4xx_of_probe(struct platform_device *op) + } + + /* Request IRQ */ +- hw->irqnum = irq_of_parse_and_map(np, 0); ++ ret = platform_get_irq(op, 0); ++ if (ret < 0) ++ goto free_host; ++ hw->irqnum = ret; ++ + ret = request_irq(hw->irqnum, spi_ppc4xx_int, + 0, "spi_ppc4xx_of", (void *)hw); + if (ret) { +diff --git a/drivers/staging/media/starfive/camss/stf-camss.c b/drivers/staging/media/starfive/camss/stf-camss.c +index fecd3e67c7a1d5..b6d34145bc191e 100644 +--- a/drivers/staging/media/starfive/camss/stf-camss.c ++++ b/drivers/staging/media/starfive/camss/stf-camss.c +@@ -358,8 +358,6 @@ static int stfcamss_probe(struct platform_device *pdev) + /* + * stfcamss_remove - Remove STFCAMSS platform device + * @pdev: Pointer to STFCAMSS platform device +- * +- * Always returns 0. + */ + static void stfcamss_remove(struct platform_device *pdev) + { +diff --git a/drivers/thermal/gov_bang_bang.c b/drivers/thermal/gov_bang_bang.c +index daed67d19efb81..863e7a4272e66f 100644 +--- a/drivers/thermal/gov_bang_bang.c ++++ b/drivers/thermal/gov_bang_bang.c +@@ -92,23 +92,21 @@ static void bang_bang_manage(struct thermal_zone_device *tz) + + for_each_trip_desc(tz, td) { + const struct thermal_trip *trip = &td->trip; ++ bool turn_on; + +- if (tz->temperature >= td->threshold || +- trip->temperature == THERMAL_TEMP_INVALID || ++ if (trip->temperature == THERMAL_TEMP_INVALID || + trip->type == THERMAL_TRIP_CRITICAL || + trip->type == THERMAL_TRIP_HOT) + continue; + + /* +- * If the initial cooling device state is "on", but the zone +- * temperature is not above the trip point, the core will not +- * call bang_bang_control() until the zone temperature reaches +- * the trip point temperature which may be never. In those +- * cases, set the initial state of the cooling device to 0. ++ * Adjust the target states for uninitialized thermal instances ++ * to the thermal zone temperature and the trip point threshold. + */ ++ turn_on = tz->temperature >= td->threshold; + list_for_each_entry(instance, &tz->thermal_instances, tz_node) { + if (!instance->initialized && instance->trip == trip) +- bang_bang_set_instance_target(instance, 0); ++ bang_bang_set_instance_target(instance, turn_on); + } + } + +diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c +index b8d889ef4fa5e6..d0e71698b35627 100644 +--- a/drivers/thermal/thermal_core.c ++++ b/drivers/thermal/thermal_core.c +@@ -323,11 +323,15 @@ static void thermal_zone_broken_disable(struct thermal_zone_device *tz) + static void thermal_zone_device_set_polling(struct thermal_zone_device *tz, + unsigned long delay) + { +- if (delay) +- mod_delayed_work(system_freezable_power_efficient_wq, +- &tz->poll_queue, delay); +- else ++ if (!delay) { + cancel_delayed_work(&tz->poll_queue); ++ return; ++ } ++ ++ if (delay > HZ) ++ delay = round_jiffies_relative(delay); ++ ++ mod_delayed_work(system_freezable_power_efficient_wq, &tz->poll_queue, delay); + } + + static void thermal_zone_recheck(struct thermal_zone_device *tz, int error) +@@ -988,20 +992,6 @@ void print_bind_err_msg(struct thermal_zone_device *tz, + tz->type, cdev->type, ret); + } + +-static void bind_cdev(struct thermal_cooling_device *cdev) +-{ +- int ret; +- struct thermal_zone_device *pos = NULL; +- +- list_for_each_entry(pos, &thermal_tz_list, node) { +- if (pos->ops.bind) { +- ret = pos->ops.bind(pos, cdev); +- if (ret) +- print_bind_err_msg(pos, cdev, ret); +- } +- } +-} +- + /** + * __thermal_cooling_device_register() - register a new thermal cooling device + * @np: a pointer to a device tree node. +@@ -1097,7 +1087,13 @@ __thermal_cooling_device_register(struct device_node *np, + list_add(&cdev->node, &thermal_cdev_list); + + /* Update binding information for 'this' new cdev */ +- bind_cdev(cdev); ++ list_for_each_entry(pos, &thermal_tz_list, node) { ++ if (pos->ops.bind) { ++ ret = pos->ops.bind(pos, cdev); ++ if (ret) ++ print_bind_err_msg(pos, cdev, ret); ++ } ++ } + + list_for_each_entry(pos, &thermal_tz_list, node) + if (atomic_cmpxchg(&pos->need_update, 1, 0)) +@@ -1335,32 +1331,6 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev) + } + EXPORT_SYMBOL_GPL(thermal_cooling_device_unregister); + +-static void bind_tz(struct thermal_zone_device *tz) +-{ +- int ret; +- struct thermal_cooling_device *pos = NULL; +- +- if (!tz->ops.bind) +- return; +- +- mutex_lock(&thermal_list_lock); +- +- list_for_each_entry(pos, &thermal_cdev_list, node) { +- ret = tz->ops.bind(tz, pos); +- if (ret) +- print_bind_err_msg(tz, pos, ret); +- } +- +- mutex_unlock(&thermal_list_lock); +-} +- +-static void thermal_set_delay_jiffies(unsigned long *delay_jiffies, int delay_ms) +-{ +- *delay_jiffies = msecs_to_jiffies(delay_ms); +- if (delay_ms > 1000) +- *delay_jiffies = round_jiffies(*delay_jiffies); +-} +- + int thermal_zone_get_crit_temp(struct thermal_zone_device *tz, int *temp) + { + const struct thermal_trip_desc *td; +@@ -1497,8 +1467,8 @@ thermal_zone_device_register_with_trips(const char *type, + td->threshold = INT_MAX; + } + +- thermal_set_delay_jiffies(&tz->passive_delay_jiffies, passive_delay); +- thermal_set_delay_jiffies(&tz->polling_delay_jiffies, polling_delay); ++ tz->polling_delay_jiffies = msecs_to_jiffies(polling_delay); ++ tz->passive_delay_jiffies = msecs_to_jiffies(passive_delay); + tz->recheck_delay_jiffies = THERMAL_RECHECK_DELAY; + + /* sys I/F */ +@@ -1542,13 +1512,23 @@ thermal_zone_device_register_with_trips(const char *type, + } + + mutex_lock(&thermal_list_lock); ++ + mutex_lock(&tz->lock); + list_add_tail(&tz->node, &thermal_tz_list); + mutex_unlock(&tz->lock); +- mutex_unlock(&thermal_list_lock); + + /* Bind cooling devices for this zone */ +- bind_tz(tz); ++ if (tz->ops.bind) { ++ struct thermal_cooling_device *cdev; ++ ++ list_for_each_entry(cdev, &thermal_cdev_list, node) { ++ result = tz->ops.bind(tz, cdev); ++ if (result) ++ print_bind_err_msg(tz, cdev, result); ++ } ++ } ++ ++ mutex_unlock(&thermal_list_lock); + + thermal_zone_device_init(tz); + /* Update the new thermal zone and mark it as already updated. */ +diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c +index afef1dd4ddf49c..fca5f25d693a72 100644 +--- a/drivers/tty/serial/8250/8250_omap.c ++++ b/drivers/tty/serial/8250/8250_omap.c +@@ -1581,7 +1581,7 @@ static int omap8250_probe(struct platform_device *pdev) + ret = devm_request_irq(&pdev->dev, up.port.irq, omap8250_irq, 0, + dev_name(&pdev->dev), priv); + if (ret < 0) +- return ret; ++ goto err; + + priv->wakeirq = irq_of_parse_and_map(np, 1); + +diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c +index 69a632fefc41f9..f8f6e9466b400d 100644 +--- a/drivers/tty/serial/qcom_geni_serial.c ++++ b/drivers/tty/serial/qcom_geni_serial.c +@@ -124,13 +124,14 @@ struct qcom_geni_serial_port { + dma_addr_t tx_dma_addr; + dma_addr_t rx_dma_addr; + bool setup; +- unsigned int baud; ++ unsigned long poll_timeout_us; + unsigned long clk_rate; + void *rx_buf; + u32 loopback; + bool brk; + + unsigned int tx_remaining; ++ unsigned int tx_queued; + int wakeup_irq; + bool rx_tx_swap; + bool cts_rts_swap; +@@ -144,6 +145,8 @@ static const struct uart_ops qcom_geni_uart_pops; + static struct uart_driver qcom_geni_console_driver; + static struct uart_driver qcom_geni_uart_driver; + ++static void qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport); ++ + static inline struct qcom_geni_serial_port *to_dev_port(struct uart_port *uport) + { + return container_of(uport, struct qcom_geni_serial_port, uport); +@@ -265,27 +268,18 @@ static bool qcom_geni_serial_secondary_active(struct uart_port *uport) + return readl(uport->membase + SE_GENI_STATUS) & S_GENI_CMD_ACTIVE; + } + +-static bool qcom_geni_serial_poll_bit(struct uart_port *uport, +- int offset, int field, bool set) ++static bool qcom_geni_serial_poll_bitfield(struct uart_port *uport, ++ unsigned int offset, u32 field, u32 val) + { + u32 reg; + struct qcom_geni_serial_port *port; +- unsigned int baud; +- unsigned int fifo_bits; + unsigned long timeout_us = 20000; + struct qcom_geni_private_data *private_data = uport->private_data; + + if (private_data->drv) { + port = to_dev_port(uport); +- baud = port->baud; +- if (!baud) +- baud = 115200; +- fifo_bits = port->tx_fifo_depth * port->tx_fifo_width; +- /* +- * Total polling iterations based on FIFO worth of bytes to be +- * sent at current baud. Add a little fluff to the wait. +- */ +- timeout_us = ((fifo_bits * USEC_PER_SEC) / baud) + 500; ++ if (port->poll_timeout_us) ++ timeout_us = port->poll_timeout_us; + } + + /* +@@ -295,7 +289,7 @@ static bool qcom_geni_serial_poll_bit(struct uart_port *uport, + timeout_us = DIV_ROUND_UP(timeout_us, 10) * 10; + while (timeout_us) { + reg = readl(uport->membase + offset); +- if ((bool)(reg & field) == set) ++ if ((reg & field) == val) + return true; + udelay(10); + timeout_us -= 10; +@@ -303,6 +297,12 @@ static bool qcom_geni_serial_poll_bit(struct uart_port *uport, + return false; + } + ++static bool qcom_geni_serial_poll_bit(struct uart_port *uport, ++ unsigned int offset, u32 field, bool set) ++{ ++ return qcom_geni_serial_poll_bitfield(uport, offset, field, set ? field : 0); ++} ++ + static void qcom_geni_serial_setup_tx(struct uart_port *uport, u32 xmit_size) + { + u32 m_cmd; +@@ -315,18 +315,16 @@ static void qcom_geni_serial_setup_tx(struct uart_port *uport, u32 xmit_size) + static void qcom_geni_serial_poll_tx_done(struct uart_port *uport) + { + int done; +- u32 irq_clear = M_CMD_DONE_EN; + + done = qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, + M_CMD_DONE_EN, true); + if (!done) { + writel(M_GENI_CMD_ABORT, uport->membase + + SE_GENI_M_CMD_CTRL_REG); +- irq_clear |= M_CMD_ABORT_EN; + qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, + M_CMD_ABORT_EN, true); ++ writel(M_CMD_ABORT_EN, uport->membase + SE_GENI_M_IRQ_CLEAR); + } +- writel(irq_clear, uport->membase + SE_GENI_M_IRQ_CLEAR); + } + + static void qcom_geni_serial_abort_rx(struct uart_port *uport) +@@ -387,6 +385,7 @@ static void qcom_geni_serial_poll_put_char(struct uart_port *uport, + unsigned char c) + { + writel(DEF_TX_WM, uport->membase + SE_GENI_TX_WATERMARK_REG); ++ writel(M_CMD_DONE_EN, uport->membase + SE_GENI_M_IRQ_CLEAR); + qcom_geni_serial_setup_tx(uport, 1); + WARN_ON(!qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, + M_TX_FIFO_WATERMARK_EN, true)); +@@ -397,6 +396,14 @@ static void qcom_geni_serial_poll_put_char(struct uart_port *uport, + #endif + + #ifdef CONFIG_SERIAL_QCOM_GENI_CONSOLE ++static void qcom_geni_serial_drain_fifo(struct uart_port *uport) ++{ ++ struct qcom_geni_serial_port *port = to_dev_port(uport); ++ ++ qcom_geni_serial_poll_bitfield(uport, SE_GENI_M_GP_LENGTH, GP_LENGTH, ++ port->tx_queued); ++} ++ + static void qcom_geni_serial_wr_char(struct uart_port *uport, unsigned char ch) + { + struct qcom_geni_private_data *private_data = uport->private_data; +@@ -431,6 +438,7 @@ __qcom_geni_serial_console_write(struct uart_port *uport, const char *s, + } + + writel(DEF_TX_WM, uport->membase + SE_GENI_TX_WATERMARK_REG); ++ writel(M_CMD_DONE_EN, uport->membase + SE_GENI_M_IRQ_CLEAR); + qcom_geni_serial_setup_tx(uport, bytes_to_send); + for (i = 0; i < count; ) { + size_t chars_to_write = 0; +@@ -471,8 +479,6 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s, + struct qcom_geni_serial_port *port; + bool locked = true; + unsigned long flags; +- u32 geni_status; +- u32 irq_en; + + WARN_ON(co->index < 0 || co->index >= GENI_UART_CONS_PORTS); + +@@ -486,40 +492,20 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s, + else + uart_port_lock_irqsave(uport, &flags); + +- geni_status = readl(uport->membase + SE_GENI_STATUS); ++ if (qcom_geni_serial_main_active(uport)) { ++ /* Wait for completion or drain FIFO */ ++ if (!locked || port->tx_remaining == 0) ++ qcom_geni_serial_poll_tx_done(uport); ++ else ++ qcom_geni_serial_drain_fifo(uport); + +- if (!locked) { +- /* +- * We can only get here if an oops is in progress then we were +- * unable to get the lock. This means we can't safely access +- * our state variables like tx_remaining. About the best we +- * can do is wait for the FIFO to be empty before we start our +- * transfer, so we'll do that. +- */ +- qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, +- M_TX_FIFO_NOT_EMPTY_EN, false); +- } else if ((geni_status & M_GENI_CMD_ACTIVE) && !port->tx_remaining) { +- /* +- * It seems we can't interrupt existing transfers if all data +- * has been sent, in which case we need to look for done first. +- */ +- qcom_geni_serial_poll_tx_done(uport); +- +- if (!kfifo_is_empty(&uport->state->port.xmit_fifo)) { +- irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); +- writel(irq_en | M_TX_FIFO_WATERMARK_EN, +- uport->membase + SE_GENI_M_IRQ_EN); +- } ++ qcom_geni_serial_cancel_tx_cmd(uport); + } + + __qcom_geni_serial_console_write(uport, s, count); + +- +- if (locked) { +- if (port->tx_remaining) +- qcom_geni_serial_setup_tx(uport, port->tx_remaining); ++ if (locked) + uart_port_unlock_irqrestore(uport, flags); +- } + } + + static void handle_rx_console(struct uart_port *uport, u32 bytes, bool drop) +@@ -700,6 +686,7 @@ static void qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport) + writel(M_CMD_CANCEL_EN, uport->membase + SE_GENI_M_IRQ_CLEAR); + + port->tx_remaining = 0; ++ port->tx_queued = 0; + } + + static void qcom_geni_serial_handle_rx_fifo(struct uart_port *uport, bool drop) +@@ -926,6 +913,7 @@ static void qcom_geni_serial_handle_tx_fifo(struct uart_port *uport, + if (!port->tx_remaining) { + qcom_geni_serial_setup_tx(uport, pending); + port->tx_remaining = pending; ++ port->tx_queued = 0; + + irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); + if (!(irq_en & M_TX_FIFO_WATERMARK_EN)) +@@ -934,6 +922,7 @@ static void qcom_geni_serial_handle_tx_fifo(struct uart_port *uport, + } + + qcom_geni_serial_send_chunk_fifo(uport, chunk); ++ port->tx_queued += chunk; + + /* + * The tx fifo watermark is level triggered and latched. Though we had +@@ -1244,11 +1233,11 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport, + unsigned long clk_rate; + u32 ver, sampling_rate; + unsigned int avg_bw_core; ++ unsigned long timeout; + + qcom_geni_serial_stop_rx(uport); + /* baud rate */ + baud = uart_get_baud_rate(uport, termios, old, 300, 4000000); +- port->baud = baud; + + sampling_rate = UART_OVERSAMPLING; + /* Sampling rate is halved for IP versions >= 2.5 */ +@@ -1326,9 +1315,21 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport, + else + tx_trans_cfg |= UART_CTS_MASK; + +- if (baud) ++ if (baud) { + uart_update_timeout(uport, termios->c_cflag, baud); + ++ /* ++ * Make sure that qcom_geni_serial_poll_bitfield() waits for ++ * the FIFO, two-word intermediate transfer register and shift ++ * register to clear. ++ * ++ * Note that uart_fifo_timeout() also adds a 20 ms margin. ++ */ ++ timeout = jiffies_to_usecs(uart_fifo_timeout(uport)); ++ timeout += 3 * timeout / port->tx_fifo_depth; ++ WRITE_ONCE(port->poll_timeout_us, timeout); ++ } ++ + if (!uart_console(uport)) + writel(port->loopback, + uport->membase + SE_UART_LOOPBACK_CFG); +diff --git a/drivers/tty/serial/rp2.c b/drivers/tty/serial/rp2.c +index 4132fcff7d4e29..8bab2aedc4991f 100644 +--- a/drivers/tty/serial/rp2.c ++++ b/drivers/tty/serial/rp2.c +@@ -577,8 +577,8 @@ static void rp2_reset_asic(struct rp2_card *card, unsigned int asic_id) + u32 clk_cfg; + + writew(1, base + RP2_GLOBAL_CMD); +- readw(base + RP2_GLOBAL_CMD); + msleep(100); ++ readw(base + RP2_GLOBAL_CMD); + writel(0, base + RP2_CLK_PRESCALER); + + /* TDM clock configuration */ +diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c +index 9967444eae10cb..1d0e7b8514ccc1 100644 +--- a/drivers/tty/serial/serial_core.c ++++ b/drivers/tty/serial/serial_core.c +@@ -2696,14 +2696,13 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options) + int ret = 0; + + tport = &state->port; +- mutex_lock(&tport->mutex); ++ ++ guard(mutex)(&tport->mutex); + + port = uart_port_check(state); + if (!port || port->type == PORT_UNKNOWN || +- !(port->ops->poll_get_char && port->ops->poll_put_char)) { +- ret = -1; +- goto out; +- } ++ !(port->ops->poll_get_char && port->ops->poll_put_char)) ++ return -1; + + pm_state = state->pm_state; + uart_change_pm(state, UART_PM_STATE_ON); +@@ -2723,10 +2722,10 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options) + ret = uart_set_options(port, NULL, baud, parity, bits, flow); + console_list_unlock(); + } +-out: ++ + if (ret) + uart_change_pm(state, pm_state); +- mutex_unlock(&tport->mutex); ++ + return ret; + } + +diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c +index cca190d1c577e9..92ff9706860ceb 100644 +--- a/drivers/ufs/host/ufs-qcom.c ++++ b/drivers/ufs/host/ufs-qcom.c +@@ -93,7 +93,7 @@ static const struct __ufs_qcom_bw_table { + [MODE_HS_RB][UFS_HS_G3][UFS_LANE_2] = { 1492582, 204800 }, + [MODE_HS_RB][UFS_HS_G4][UFS_LANE_2] = { 2915200, 409600 }, + [MODE_HS_RB][UFS_HS_G5][UFS_LANE_2] = { 5836800, 819200 }, +- [MODE_MAX][0][0] = { 7643136, 307200 }, ++ [MODE_MAX][0][0] = { 7643136, 819200 }, + }; + + static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host); +diff --git a/drivers/usb/cdns3/cdnsp-ring.c b/drivers/usb/cdns3/cdnsp-ring.c +index dbd83d321bca01..46852529499d16 100644 +--- a/drivers/usb/cdns3/cdnsp-ring.c ++++ b/drivers/usb/cdns3/cdnsp-ring.c +@@ -718,7 +718,8 @@ int cdnsp_remove_request(struct cdnsp_device *pdev, + seg = cdnsp_trb_in_td(pdev, cur_td->start_seg, cur_td->first_trb, + cur_td->last_trb, hw_deq); + +- if (seg && (pep->ep_state & EP_ENABLED)) ++ if (seg && (pep->ep_state & EP_ENABLED) && ++ !(pep->ep_state & EP_DIS_IN_RROGRESS)) + cdnsp_find_new_dequeue_state(pdev, pep, preq->request.stream_id, + cur_td, &deq_state); + else +@@ -736,7 +737,8 @@ int cdnsp_remove_request(struct cdnsp_device *pdev, + * During disconnecting all endpoint will be disabled so we don't + * have to worry about updating dequeue pointer. + */ +- if (pdev->cdnsp_state & CDNSP_STATE_DISCONNECT_PENDING) { ++ if (pdev->cdnsp_state & CDNSP_STATE_DISCONNECT_PENDING || ++ pep->ep_state & EP_DIS_IN_RROGRESS) { + status = -ESHUTDOWN; + ret = cdnsp_cmd_set_deq(pdev, pep, &deq_state); + } +diff --git a/drivers/usb/cdns3/host.c b/drivers/usb/cdns3/host.c +index ceca4d839dfd42..7ba760ee62e331 100644 +--- a/drivers/usb/cdns3/host.c ++++ b/drivers/usb/cdns3/host.c +@@ -62,7 +62,9 @@ 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 const struct xhci_plat_priv xhci_plat_cdnsp_xhci = { ++ .quirks = XHCI_CDNS_SCTX_QUIRK, ++}; + + static int __cdns_host_init(struct cdns *cdns) + { +diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c +index 0c1b69d944ca45..605fea4611029b 100644 +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -962,10 +962,12 @@ static int get_serial_info(struct tty_struct *tty, struct serial_struct *ss) + struct acm *acm = tty->driver_data; + + ss->line = acm->minor; ++ mutex_lock(&acm->port.mutex); + ss->close_delay = jiffies_to_msecs(acm->port.close_delay) / 10; + ss->closing_wait = acm->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? + ASYNC_CLOSING_WAIT_NONE : + jiffies_to_msecs(acm->port.closing_wait) / 10; ++ mutex_unlock(&acm->port.mutex); + return 0; + } + +diff --git a/drivers/usb/dwc2/drd.c b/drivers/usb/dwc2/drd.c +index a8605b02115b1c..1ad8fa3f862a15 100644 +--- a/drivers/usb/dwc2/drd.c ++++ b/drivers/usb/dwc2/drd.c +@@ -127,6 +127,15 @@ static int dwc2_drd_role_sw_set(struct usb_role_switch *sw, enum usb_role role) + role = USB_ROLE_DEVICE; + } + ++ if ((IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || ++ IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)) && ++ dwc2_is_device_mode(hsotg) && ++ hsotg->lx_state == DWC2_L2 && ++ hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE && ++ hsotg->bus_suspended && ++ !hsotg->params.no_clock_gating) ++ dwc2_gadget_exit_clock_gating(hsotg, 0); ++ + if (role == USB_ROLE_HOST) { + already = dwc2_ovr_avalid(hsotg, true); + } else if (role == USB_ROLE_DEVICE) { +diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c +index f37b0d8386c1a9..ff7bee78bcc492 100644 +--- a/drivers/usb/gadget/udc/dummy_hcd.c ++++ b/drivers/usb/gadget/udc/dummy_hcd.c +@@ -1304,7 +1304,8 @@ static int dummy_urb_enqueue( + + /* kick the scheduler, it'll do the rest */ + if (!hrtimer_active(&dum_hcd->timer)) +- hrtimer_start(&dum_hcd->timer, ns_to_ktime(DUMMY_TIMER_INT_NSECS), HRTIMER_MODE_REL); ++ hrtimer_start(&dum_hcd->timer, ns_to_ktime(DUMMY_TIMER_INT_NSECS), ++ HRTIMER_MODE_REL_SOFT); + + done: + spin_unlock_irqrestore(&dum_hcd->dum->lock, flags); +@@ -1325,7 +1326,7 @@ static int dummy_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) + rc = usb_hcd_check_unlink_urb(hcd, urb, status); + if (!rc && dum_hcd->rh_state != DUMMY_RH_RUNNING && + !list_empty(&dum_hcd->urbp_list)) +- hrtimer_start(&dum_hcd->timer, ns_to_ktime(0), HRTIMER_MODE_REL); ++ hrtimer_start(&dum_hcd->timer, ns_to_ktime(0), HRTIMER_MODE_REL_SOFT); + + spin_unlock_irqrestore(&dum_hcd->dum->lock, flags); + return rc; +@@ -1995,7 +1996,8 @@ static enum hrtimer_restart dummy_timer(struct hrtimer *t) + dum_hcd->udev = NULL; + } else if (dum_hcd->rh_state == DUMMY_RH_RUNNING) { + /* want a 1 msec delay here */ +- hrtimer_start(&dum_hcd->timer, ns_to_ktime(DUMMY_TIMER_INT_NSECS), HRTIMER_MODE_REL); ++ hrtimer_start(&dum_hcd->timer, ns_to_ktime(DUMMY_TIMER_INT_NSECS), ++ HRTIMER_MODE_REL_SOFT); + } + + spin_unlock_irqrestore(&dum->lock, flags); +@@ -2389,7 +2391,7 @@ static int dummy_bus_resume(struct usb_hcd *hcd) + dum_hcd->rh_state = DUMMY_RH_RUNNING; + set_link_state(dum_hcd); + if (!list_empty(&dum_hcd->urbp_list)) +- hrtimer_start(&dum_hcd->timer, ns_to_ktime(0), HRTIMER_MODE_REL); ++ hrtimer_start(&dum_hcd->timer, ns_to_ktime(0), HRTIMER_MODE_REL_SOFT); + hcd->state = HC_STATE_RUNNING; + } + spin_unlock_irq(&dum_hcd->dum->lock); +@@ -2467,7 +2469,7 @@ static DEVICE_ATTR_RO(urbs); + + static int dummy_start_ss(struct dummy_hcd *dum_hcd) + { +- hrtimer_init(&dum_hcd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ++ hrtimer_init(&dum_hcd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT); + dum_hcd->timer.function = dummy_timer; + dum_hcd->rh_state = DUMMY_RH_RUNNING; + dum_hcd->stream_en_ep = 0; +@@ -2497,7 +2499,7 @@ static int dummy_start(struct usb_hcd *hcd) + return dummy_start_ss(dum_hcd); + + spin_lock_init(&dum_hcd->dum->lock); +- hrtimer_init(&dum_hcd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ++ hrtimer_init(&dum_hcd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT); + dum_hcd->timer.function = dummy_timer; + dum_hcd->rh_state = DUMMY_RH_RUNNING; + +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index f591ddd086627a..fa3ee53df0ecc5 100644 +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -2325,7 +2325,10 @@ xhci_add_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir, + erst_base = xhci_read_64(xhci, &ir->ir_set->erst_base); + erst_base &= ERST_BASE_RSVDP; + erst_base |= ir->erst.erst_dma_addr & ~ERST_BASE_RSVDP; +- xhci_write_64(xhci, erst_base, &ir->ir_set->erst_base); ++ if (xhci->quirks & XHCI_WRITE_64_HI_LO) ++ hi_lo_writeq(erst_base, &ir->ir_set->erst_base); ++ else ++ xhci_write_64(xhci, erst_base, &ir->ir_set->erst_base); + + /* Set the event ring dequeue address of this interrupter */ + xhci_set_hc_event_deq(xhci, ir); +diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c +index dc1e345ab67ea8..994fd8b38bd015 100644 +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -55,6 +55,9 @@ + #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI 0x51ed + #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_N_PCH_XHCI 0x54ed + ++#define PCI_VENDOR_ID_PHYTIUM 0x1db7 ++#define PCI_DEVICE_ID_PHYTIUM_XHCI 0xdc27 ++ + /* Thunderbolt */ + #define PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI 0x1138 + #define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_XHCI 0x15b5 +@@ -78,6 +81,9 @@ + #define PCI_DEVICE_ID_ASMEDIA_2142_XHCI 0x2142 + #define PCI_DEVICE_ID_ASMEDIA_3242_XHCI 0x3242 + ++#define PCI_DEVICE_ID_CADENCE 0x17CD ++#define PCI_DEVICE_ID_CADENCE_SSP 0x0200 ++ + static const char hcd_name[] = "xhci_hcd"; + + static struct hc_driver __read_mostly xhci_pci_hc_driver; +@@ -416,6 +422,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) + if (pdev->vendor == PCI_VENDOR_ID_VIA) + xhci->quirks |= XHCI_RESET_ON_RESUME; + ++ if (pdev->vendor == PCI_VENDOR_ID_PHYTIUM && ++ pdev->device == PCI_DEVICE_ID_PHYTIUM_XHCI) ++ xhci->quirks |= XHCI_RESET_ON_RESUME; ++ + /* See https://bugzilla.kernel.org/show_bug.cgi?id=79511 */ + if (pdev->vendor == PCI_VENDOR_ID_VIA && + pdev->device == 0x3432) +@@ -473,6 +483,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) + xhci->quirks |= XHCI_ZHAOXIN_TRB_FETCH; + } + ++ if (pdev->vendor == PCI_DEVICE_ID_CADENCE && ++ pdev->device == PCI_DEVICE_ID_CADENCE_SSP) ++ xhci->quirks |= XHCI_CDNS_SCTX_QUIRK; ++ + /* xHC spec requires PCI devices to support D3hot and D3cold */ + if (xhci->hci_version >= 0x120) + xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW; +@@ -655,8 +669,10 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) + static void xhci_pci_remove(struct pci_dev *dev) + { + struct xhci_hcd *xhci; ++ bool set_power_d3; + + xhci = hcd_to_xhci(pci_get_drvdata(dev)); ++ set_power_d3 = xhci->quirks & XHCI_SPURIOUS_WAKEUP; + + xhci->xhc_state |= XHCI_STATE_REMOVING; + +@@ -669,11 +685,11 @@ static void xhci_pci_remove(struct pci_dev *dev) + xhci->shared_hcd = NULL; + } + ++ usb_hcd_pci_remove(dev); ++ + /* Workaround for spurious wakeups at shutdown with HSW */ +- if (xhci->quirks & XHCI_SPURIOUS_WAKEUP) ++ if (set_power_d3) + pci_set_power_state(dev, PCI_D3hot); +- +- usb_hcd_pci_remove(dev); + } + + /* +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index fd0cde3d1569c7..0fe6bef6c39800 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -1426,6 +1426,20 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id, + struct xhci_stream_ctx *ctx = + &ep->stream_info->stream_ctx_array[stream_id]; + deq = le64_to_cpu(ctx->stream_ring) & SCTX_DEQ_MASK; ++ ++ /* ++ * Cadence xHCI controllers store some endpoint state ++ * information within Rsvd0 fields of Stream Endpoint ++ * context. This field is not cleared during Set TR ++ * Dequeue Pointer command which causes XDMA to skip ++ * over transfer ring and leads to data loss on stream ++ * pipe. ++ * To fix this issue driver must clear Rsvd0 field. ++ */ ++ if (xhci->quirks & XHCI_CDNS_SCTX_QUIRK) { ++ ctx->reserved[0] = 0; ++ ctx->reserved[1] = 0; ++ } + } else { + deq = le64_to_cpu(ep_ctx->deq) & ~EP_CTX_CYCLE_MASK; + } +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index 78d014c4d884a2..ac8da8a7df86b7 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -17,6 +17,7 @@ + #include <linux/kernel.h> + #include <linux/usb/hcd.h> + #include <linux/io-64-nonatomic-lo-hi.h> ++#include <linux/io-64-nonatomic-hi-lo.h> + + /* Code sharing between pci-quirks and xhci hcd */ + #include "xhci-ext-caps.h" +@@ -1628,6 +1629,8 @@ struct xhci_hcd { + #define XHCI_RESET_TO_DEFAULT BIT_ULL(44) + #define XHCI_ZHAOXIN_TRB_FETCH BIT_ULL(45) + #define XHCI_ZHAOXIN_HOST BIT_ULL(46) ++#define XHCI_WRITE_64_HI_LO BIT_ULL(47) ++#define XHCI_CDNS_SCTX_QUIRK BIT_ULL(48) + + unsigned int num_active_eps; + unsigned int limit_active_eps; +diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c +index c8098e9b432e13..62b5a30edc4267 100644 +--- a/drivers/usb/misc/appledisplay.c ++++ b/drivers/usb/misc/appledisplay.c +@@ -107,7 +107,12 @@ static void appledisplay_complete(struct urb *urb) + case ACD_BTN_BRIGHT_UP: + case ACD_BTN_BRIGHT_DOWN: + pdata->button_pressed = 1; +- schedule_delayed_work(&pdata->work, 0); ++ /* ++ * there is a window during which no device ++ * is registered ++ */ ++ if (pdata->bd ) ++ schedule_delayed_work(&pdata->work, 0); + break; + case ACD_BTN_NONE: + default: +@@ -202,6 +207,7 @@ static int appledisplay_probe(struct usb_interface *iface, + const struct usb_device_id *id) + { + struct backlight_properties props; ++ struct backlight_device *backlight; + struct appledisplay *pdata; + struct usb_device *udev = interface_to_usbdev(iface); + struct usb_endpoint_descriptor *endpoint; +@@ -272,13 +278,14 @@ static int appledisplay_probe(struct usb_interface *iface, + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; + props.max_brightness = 0xff; +- pdata->bd = backlight_device_register(bl_name, NULL, pdata, ++ backlight = backlight_device_register(bl_name, NULL, pdata, + &appledisplay_bl_data, &props); +- if (IS_ERR(pdata->bd)) { ++ if (IS_ERR(backlight)) { + dev_err(&iface->dev, "Backlight registration failed\n"); +- retval = PTR_ERR(pdata->bd); ++ retval = PTR_ERR(backlight); + goto error; + } ++ pdata->bd = backlight; + + /* Try to get brightness */ + brightness = appledisplay_bl_get_brightness(pdata->bd); +diff --git a/drivers/usb/misc/cypress_cy7c63.c b/drivers/usb/misc/cypress_cy7c63.c +index cecd7693b7413c..75f5a740cba397 100644 +--- a/drivers/usb/misc/cypress_cy7c63.c ++++ b/drivers/usb/misc/cypress_cy7c63.c +@@ -88,6 +88,9 @@ static int vendor_command(struct cypress *dev, unsigned char request, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER, + address, data, iobuf, CYPRESS_MAX_REQSIZE, + USB_CTRL_GET_TIMEOUT); ++ /* we must not process garbage */ ++ if (retval < 2) ++ goto err_buf; + + /* store returned data (more READs to be added) */ + switch (request) { +@@ -107,6 +110,7 @@ static int vendor_command(struct cypress *dev, unsigned char request, + break; + } + ++err_buf: + kfree(iobuf); + error: + return retval; +diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c +index 9a0649d2369354..6adaaf66c14d7b 100644 +--- a/drivers/usb/misc/yurex.c ++++ b/drivers/usb/misc/yurex.c +@@ -404,7 +404,6 @@ static ssize_t yurex_read(struct file *file, char __user *buffer, size_t count, + struct usb_yurex *dev; + int len = 0; + char in_buffer[MAX_S64_STRLEN]; +- unsigned long flags; + + dev = file->private_data; + +@@ -419,9 +418,9 @@ static ssize_t yurex_read(struct file *file, char __user *buffer, size_t count, + return -EIO; + } + +- spin_lock_irqsave(&dev->lock, flags); ++ spin_lock_irq(&dev->lock); + scnprintf(in_buffer, MAX_S64_STRLEN, "%lld\n", dev->bbu); +- spin_unlock_irqrestore(&dev->lock, flags); ++ spin_unlock_irq(&dev->lock); + mutex_unlock(&dev->io_mutex); + + return simple_read_from_buffer(buffer, count, ppos, in_buffer, len); +@@ -511,8 +510,11 @@ static ssize_t yurex_write(struct file *file, const char __user *user_buffer, + __func__, retval); + goto error; + } +- if (set && timeout) ++ if (set && timeout) { ++ spin_lock_irq(&dev->lock); + dev->bbu = c2; ++ spin_unlock_irq(&dev->lock); ++ } + return timeout ? count : -EIO; + + error: +diff --git a/drivers/vdpa/mlx5/core/mr.c b/drivers/vdpa/mlx5/core/mr.c +index 4758914ccf8608..bf56f3d6962533 100644 +--- a/drivers/vdpa/mlx5/core/mr.c ++++ b/drivers/vdpa/mlx5/core/mr.c +@@ -581,6 +581,9 @@ static void mlx5_vdpa_show_mr_leaks(struct mlx5_vdpa_dev *mvdev) + + void mlx5_vdpa_destroy_mr_resources(struct mlx5_vdpa_dev *mvdev) + { ++ if (!mvdev->res.valid) ++ return; ++ + for (int i = 0; i < MLX5_VDPA_NUM_AS; i++) + mlx5_vdpa_update_mr(mvdev, NULL, i); + +diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c +index 6b9c12acf4381a..b3d2a53f9bb77f 100644 +--- a/drivers/vhost/vdpa.c ++++ b/drivers/vhost/vdpa.c +@@ -209,11 +209,9 @@ static void vhost_vdpa_setup_vq_irq(struct vhost_vdpa *v, u16 qid) + if (irq < 0) + return; + +- irq_bypass_unregister_producer(&vq->call_ctx.producer); + if (!vq->call_ctx.ctx) + return; + +- vq->call_ctx.producer.token = vq->call_ctx.ctx; + vq->call_ctx.producer.irq = irq; + ret = irq_bypass_register_producer(&vq->call_ctx.producer); + if (unlikely(ret)) +@@ -709,6 +707,14 @@ static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd, + vq->last_avail_idx = vq_state.split.avail_index; + } + break; ++ case VHOST_SET_VRING_CALL: ++ if (vq->call_ctx.ctx) { ++ if (ops->get_status(vdpa) & ++ VIRTIO_CONFIG_S_DRIVER_OK) ++ vhost_vdpa_unsetup_vq_irq(v, idx); ++ vq->call_ctx.producer.token = NULL; ++ } ++ break; + } + + r = vhost_vring_ioctl(&v->vdev, cmd, argp); +@@ -747,13 +753,16 @@ static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd, + cb.callback = vhost_vdpa_virtqueue_cb; + cb.private = vq; + cb.trigger = vq->call_ctx.ctx; ++ vq->call_ctx.producer.token = vq->call_ctx.ctx; ++ if (ops->get_status(vdpa) & ++ VIRTIO_CONFIG_S_DRIVER_OK) ++ vhost_vdpa_setup_vq_irq(v, idx); + } else { + cb.callback = NULL; + cb.private = NULL; + cb.trigger = NULL; + } + ops->set_vq_cb(vdpa, idx, &cb); +- vhost_vdpa_setup_vq_irq(v, idx); + break; + + case VHOST_SET_VRING_NUM: +@@ -1421,6 +1430,7 @@ static int vhost_vdpa_open(struct inode *inode, struct file *filep) + for (i = 0; i < nvqs; i++) { + vqs[i] = &v->vqs[i]; + vqs[i]->handle_kick = handle_vq_kick; ++ vqs[i]->call_ctx.ctx = NULL; + } + vhost_dev_init(dev, vqs, nvqs, 0, 0, 0, false, + vhost_vdpa_process_iotlb_msg); +diff --git a/drivers/video/fbdev/hpfb.c b/drivers/video/fbdev/hpfb.c +index 66fac8e5393e08..a1144b15098266 100644 +--- a/drivers/video/fbdev/hpfb.c ++++ b/drivers/video/fbdev/hpfb.c +@@ -345,6 +345,7 @@ static int hpfb_dio_probe(struct dio_dev *d, const struct dio_device_id *ent) + if (hpfb_init_one(paddr, vaddr)) { + if (d->scode >= DIOII_SCBASE) + iounmap((void *)vaddr); ++ release_mem_region(d->resource.start, resource_size(&d->resource)); + return -ENOMEM; + } + return 0; +diff --git a/drivers/video/fbdev/xen-fbfront.c b/drivers/video/fbdev/xen-fbfront.c +index 66d4628a96ae04..c90f48ebb15e3f 100644 +--- a/drivers/video/fbdev/xen-fbfront.c ++++ b/drivers/video/fbdev/xen-fbfront.c +@@ -407,6 +407,7 @@ static int xenfb_probe(struct xenbus_device *dev, + /* complete the abuse: */ + fb_info->pseudo_palette = fb_info->par; + fb_info->par = info; ++ fb_info->device = &dev->dev; + + fb_info->screen_buffer = info->fb; + +diff --git a/drivers/watchdog/imx_sc_wdt.c b/drivers/watchdog/imx_sc_wdt.c +index e51fe1b78518f4..d73076b686d8ca 100644 +--- a/drivers/watchdog/imx_sc_wdt.c ++++ b/drivers/watchdog/imx_sc_wdt.c +@@ -216,29 +216,6 @@ static int imx_sc_wdt_probe(struct platform_device *pdev) + return devm_watchdog_register_device(dev, wdog); + } + +-static int __maybe_unused imx_sc_wdt_suspend(struct device *dev) +-{ +- struct imx_sc_wdt_device *imx_sc_wdd = dev_get_drvdata(dev); +- +- if (watchdog_active(&imx_sc_wdd->wdd)) +- imx_sc_wdt_stop(&imx_sc_wdd->wdd); +- +- return 0; +-} +- +-static int __maybe_unused imx_sc_wdt_resume(struct device *dev) +-{ +- struct imx_sc_wdt_device *imx_sc_wdd = dev_get_drvdata(dev); +- +- if (watchdog_active(&imx_sc_wdd->wdd)) +- imx_sc_wdt_start(&imx_sc_wdd->wdd); +- +- return 0; +-} +- +-static SIMPLE_DEV_PM_OPS(imx_sc_wdt_pm_ops, +- imx_sc_wdt_suspend, imx_sc_wdt_resume); +- + static const struct of_device_id imx_sc_wdt_dt_ids[] = { + { .compatible = "fsl,imx-sc-wdt", }, + { /* sentinel */ } +@@ -250,7 +227,6 @@ static struct platform_driver imx_sc_wdt_driver = { + .driver = { + .name = "imx-sc-wdt", + .of_match_table = imx_sc_wdt_dt_ids, +- .pm = &imx_sc_wdt_pm_ops, + }, + }; + module_platform_driver(imx_sc_wdt_driver); +diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c +index 6579ae3f6dac22..5e83d1e0bd184c 100644 +--- a/drivers/xen/swiotlb-xen.c ++++ b/drivers/xen/swiotlb-xen.c +@@ -78,9 +78,15 @@ static inline int range_straddles_page_boundary(phys_addr_t p, size_t size) + { + unsigned long next_bfn, xen_pfn = XEN_PFN_DOWN(p); + unsigned int i, nr_pages = XEN_PFN_UP(xen_offset_in_page(p) + size); ++ phys_addr_t algn = 1ULL << (get_order(size) + PAGE_SHIFT); + + next_bfn = pfn_to_bfn(xen_pfn); + ++ /* If buffer is physically aligned, ensure DMA alignment. */ ++ if (IS_ALIGNED(p, algn) && ++ !IS_ALIGNED((phys_addr_t)next_bfn << XEN_PAGE_SHIFT, algn)) ++ return 1; ++ + for (i = 1; i < nr_pages; i++) + if (pfn_to_bfn(++xen_pfn) != ++next_bfn) + return 1; +@@ -140,7 +146,7 @@ xen_swiotlb_alloc_coherent(struct device *dev, size_t size, + void *ret; + + /* Align the allocation to the Xen page size */ +- size = 1UL << (order + XEN_PAGE_SHIFT); ++ size = ALIGN(size, XEN_PAGE_SIZE); + + ret = (void *)__get_free_pages(flags, get_order(size)); + if (!ret) +@@ -172,7 +178,7 @@ xen_swiotlb_free_coherent(struct device *dev, size_t size, void *vaddr, + int order = get_order(size); + + /* Convert the size to actually allocated. */ +- size = 1UL << (order + XEN_PAGE_SHIFT); ++ size = ALIGN(size, XEN_PAGE_SIZE); + + if (WARN_ON_ONCE(dma_handle + size - 1 > dev->coherent_dma_mask) || + WARN_ON_ONCE(range_straddles_page_boundary(phys, size))) +diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c +index 1f5db686366316..bb404bfce036b4 100644 +--- a/fs/autofs/inode.c ++++ b/fs/autofs/inode.c +@@ -172,8 +172,7 @@ static int autofs_parse_fd(struct fs_context *fc, struct autofs_sb_info *sbi, + ret = autofs_check_pipe(pipe); + if (ret < 0) { + errorf(fc, "Invalid/unusable pipe"); +- if (param->type != fs_value_is_file) +- fput(pipe); ++ fput(pipe); + return -EBADF; + } + +diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h +index 6ed495ca7a311d..bc69bf0dbe93d2 100644 +--- a/fs/btrfs/btrfs_inode.h ++++ b/fs/btrfs/btrfs_inode.h +@@ -126,6 +126,7 @@ struct btrfs_inode { + * logged_trans), to access/update delalloc_bytes, new_delalloc_bytes, + * defrag_bytes, disk_i_size, outstanding_extents, csum_bytes and to + * update the VFS' inode number of bytes used. ++ * Also protects setting struct file::private_data. + */ + spinlock_t lock; + +diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h +index b2e4b30b8fae91..a4296ce1de7178 100644 +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -457,6 +457,8 @@ struct btrfs_file_private { + void *filldir_buf; + u64 last_index; + struct extent_state *llseek_cached_state; ++ /* Task that allocated this structure. */ ++ struct task_struct *owner_task; + }; + + static inline u32 BTRFS_LEAF_DATA_SIZE(const struct btrfs_fs_info *info) +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 55be8a7f0bb188..79dd2d9a62d9df 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -6426,13 +6426,13 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range) + continue; + + ret = btrfs_trim_free_extents(device, &group_trimmed); ++ ++ trimmed += group_trimmed; + if (ret) { + dev_failed++; + dev_ret = ret; + break; + } +- +- trimmed += group_trimmed; + } + mutex_unlock(&fs_devices->device_list_mutex); + +diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c +index 66dfee87390672..0a14379a2d517d 100644 +--- a/fs/btrfs/file.c ++++ b/fs/btrfs/file.c +@@ -3689,7 +3689,7 @@ static bool find_desired_extent_in_hole(struct btrfs_inode *inode, int whence, + static loff_t find_desired_extent(struct file *file, loff_t offset, int whence) + { + struct btrfs_inode *inode = BTRFS_I(file->f_mapping->host); +- struct btrfs_file_private *private = file->private_data; ++ struct btrfs_file_private *private; + struct btrfs_fs_info *fs_info = inode->root->fs_info; + struct extent_state *cached_state = NULL; + struct extent_state **delalloc_cached_state; +@@ -3717,7 +3717,19 @@ static loff_t find_desired_extent(struct file *file, loff_t offset, int whence) + inode_get_bytes(&inode->vfs_inode) == i_size) + return i_size; + +- if (!private) { ++ spin_lock(&inode->lock); ++ private = file->private_data; ++ spin_unlock(&inode->lock); ++ ++ if (private && private->owner_task != current) { ++ /* ++ * Not allocated by us, don't use it as its cached state is used ++ * by the task that allocated it and we don't want neither to ++ * mess with it nor get incorrect results because it reflects an ++ * invalid state for the current task. ++ */ ++ private = NULL; ++ } else if (!private) { + private = kzalloc(sizeof(*private), GFP_KERNEL); + /* + * No worries if memory allocation failed. +@@ -3725,7 +3737,23 @@ static loff_t find_desired_extent(struct file *file, loff_t offset, int whence) + * lseek SEEK_HOLE/DATA calls to a file when there's delalloc, + * so everything will still be correct. + */ +- file->private_data = private; ++ if (private) { ++ bool free = false; ++ ++ private->owner_task = current; ++ ++ spin_lock(&inode->lock); ++ if (file->private_data) ++ free = true; ++ else ++ file->private_data = private; ++ spin_unlock(&inode->lock); ++ ++ if (free) { ++ kfree(private); ++ private = NULL; ++ } ++ } + } + + if (private) +diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c +index c1b0556e403683..4a30f34bc8300a 100644 +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -543,13 +543,11 @@ static noinline int btrfs_ioctl_fitrim(struct btrfs_fs_info *fs_info, + + range.minlen = max(range.minlen, minlen); + ret = btrfs_trim_fs(fs_info, &range); +- if (ret < 0) +- return ret; + + if (copy_to_user(arg, &range, sizeof(range))) + return -EFAULT; + +- return 0; ++ return ret; + } + + int __pure btrfs_is_empty_uuid(u8 *uuid) +diff --git a/fs/btrfs/subpage.c b/fs/btrfs/subpage.c +index 54736f6238e659..831e96b607f505 100644 +--- a/fs/btrfs/subpage.c ++++ b/fs/btrfs/subpage.c +@@ -766,8 +766,14 @@ void btrfs_folio_unlock_writer(struct btrfs_fs_info *fs_info, + } + + #define GET_SUBPAGE_BITMAP(subpage, subpage_info, name, dst) \ +- bitmap_cut(dst, subpage->bitmaps, 0, \ +- subpage_info->name##_offset, subpage_info->bitmap_nr_bits) ++{ \ ++ const int bitmap_nr_bits = subpage_info->bitmap_nr_bits; \ ++ \ ++ ASSERT(bitmap_nr_bits < BITS_PER_LONG); \ ++ *dst = bitmap_read(subpage->bitmaps, \ ++ subpage_info->name##_offset, \ ++ bitmap_nr_bits); \ ++} + + void __cold btrfs_subpage_dump_bitmap(const struct btrfs_fs_info *fs_info, + struct folio *folio, u64 start, u32 len) +diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c +index de1c063bc39dbe..42e2ec3cd1c11e 100644 +--- a/fs/btrfs/tree-checker.c ++++ b/fs/btrfs/tree-checker.c +@@ -1499,7 +1499,7 @@ static int check_extent_item(struct extent_buffer *leaf, + dref_objectid > BTRFS_LAST_FREE_OBJECTID)) { + extent_err(leaf, slot, + "invalid data ref objectid value %llu", +- dref_root); ++ dref_objectid); + return -EUCLEAN; + } + if (unlikely(!IS_ALIGNED(dref_offset, +diff --git a/fs/cachefiles/xattr.c b/fs/cachefiles/xattr.c +index 4dd8a993c60a8b..7c6f260a3be567 100644 +--- a/fs/cachefiles/xattr.c ++++ b/fs/cachefiles/xattr.c +@@ -64,9 +64,15 @@ int cachefiles_set_object_xattr(struct cachefiles_object *object) + memcpy(buf->data, fscache_get_aux(object->cookie), len); + + ret = cachefiles_inject_write_error(); +- if (ret == 0) +- ret = vfs_setxattr(&nop_mnt_idmap, dentry, cachefiles_xattr_cache, +- buf, sizeof(struct cachefiles_xattr) + len, 0); ++ if (ret == 0) { ++ ret = mnt_want_write_file(file); ++ if (ret == 0) { ++ ret = vfs_setxattr(&nop_mnt_idmap, dentry, ++ cachefiles_xattr_cache, buf, ++ sizeof(struct cachefiles_xattr) + len, 0); ++ mnt_drop_write_file(file); ++ } ++ } + if (ret < 0) { + trace_cachefiles_vfs_error(object, file_inode(file), ret, + cachefiles_trace_setxattr_error); +@@ -151,8 +157,14 @@ int cachefiles_remove_object_xattr(struct cachefiles_cache *cache, + int ret; + + ret = cachefiles_inject_remove_error(); +- if (ret == 0) +- ret = vfs_removexattr(&nop_mnt_idmap, dentry, cachefiles_xattr_cache); ++ if (ret == 0) { ++ ret = mnt_want_write(cache->mnt); ++ if (ret == 0) { ++ ret = vfs_removexattr(&nop_mnt_idmap, dentry, ++ cachefiles_xattr_cache); ++ mnt_drop_write(cache->mnt); ++ } ++ } + if (ret < 0) { + trace_cachefiles_vfs_error(object, d_inode(dentry), ret, + cachefiles_trace_remxattr_error); +@@ -208,9 +220,15 @@ bool cachefiles_set_volume_xattr(struct cachefiles_volume *volume) + memcpy(buf->data, p, volume->vcookie->coherency_len); + + ret = cachefiles_inject_write_error(); +- if (ret == 0) +- ret = vfs_setxattr(&nop_mnt_idmap, dentry, cachefiles_xattr_cache, +- buf, len, 0); ++ if (ret == 0) { ++ ret = mnt_want_write(volume->cache->mnt); ++ if (ret == 0) { ++ ret = vfs_setxattr(&nop_mnt_idmap, dentry, ++ cachefiles_xattr_cache, ++ buf, len, 0); ++ mnt_drop_write(volume->cache->mnt); ++ } ++ } + if (ret < 0) { + trace_cachefiles_vfs_error(NULL, d_inode(dentry), ret, + cachefiles_trace_setxattr_error); +diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c +index 8fd928899a59e4..66d9b3b4c5881d 100644 +--- a/fs/debugfs/inode.c ++++ b/fs/debugfs/inode.c +@@ -89,12 +89,14 @@ enum { + Opt_uid, + Opt_gid, + Opt_mode, ++ Opt_source, + }; + + static const struct fs_parameter_spec debugfs_param_specs[] = { +- fsparam_u32 ("gid", Opt_gid), ++ fsparam_gid ("gid", Opt_gid), + fsparam_u32oct ("mode", Opt_mode), +- fsparam_u32 ("uid", Opt_uid), ++ fsparam_uid ("uid", Opt_uid), ++ fsparam_string ("source", Opt_source), + {} + }; + +@@ -102,8 +104,6 @@ static int debugfs_parse_param(struct fs_context *fc, struct fs_parameter *param + { + struct debugfs_fs_info *opts = fc->s_fs_info; + struct fs_parse_result result; +- kuid_t uid; +- kgid_t gid; + int opt; + + opt = fs_parse(fc, debugfs_param_specs, param, &result); +@@ -120,20 +120,20 @@ static int debugfs_parse_param(struct fs_context *fc, struct fs_parameter *param + + switch (opt) { + case Opt_uid: +- uid = make_kuid(current_user_ns(), result.uint_32); +- if (!uid_valid(uid)) +- return invalf(fc, "Unknown uid"); +- opts->uid = uid; ++ opts->uid = result.uid; + break; + case Opt_gid: +- gid = make_kgid(current_user_ns(), result.uint_32); +- if (!gid_valid(gid)) +- return invalf(fc, "Unknown gid"); +- opts->gid = gid; ++ opts->gid = result.gid; + break; + case Opt_mode: + opts->mode = result.uint_32 & S_IALLUGO; + break; ++ case Opt_source: ++ if (fc->source) ++ return invalfc(fc, "Multiple sources specified"); ++ fc->source = param->string; ++ param->string = NULL; ++ break; + /* + * We might like to report bad mount options here; + * but traditionally debugfs has ignored all mount options +diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c +index 5f6439a63af798..f2cab9e4f3bcd8 100644 +--- a/fs/erofs/inode.c ++++ b/fs/erofs/inode.c +@@ -178,12 +178,14 @@ static int erofs_fill_symlink(struct inode *inode, void *kaddr, + unsigned int m_pofs) + { + struct erofs_inode *vi = EROFS_I(inode); +- unsigned int bsz = i_blocksize(inode); ++ loff_t off; + char *lnk; + +- /* if it cannot be handled with fast symlink scheme */ +- if (vi->datalayout != EROFS_INODE_FLAT_INLINE || +- inode->i_size >= bsz || inode->i_size < 0) { ++ m_pofs += vi->xattr_isize; ++ /* check if it cannot be handled with fast symlink scheme */ ++ if (vi->datalayout != EROFS_INODE_FLAT_INLINE || inode->i_size < 0 || ++ check_add_overflow(m_pofs, inode->i_size, &off) || ++ off > i_blocksize(inode)) { + inode->i_op = &erofs_symlink_iops; + return 0; + } +@@ -192,16 +194,6 @@ static int erofs_fill_symlink(struct inode *inode, void *kaddr, + if (!lnk) + return -ENOMEM; + +- m_pofs += vi->xattr_isize; +- /* inline symlink data shouldn't cross block boundary */ +- if (m_pofs + inode->i_size > bsz) { +- kfree(lnk); +- erofs_err(inode->i_sb, +- "inline data cross block boundary @ nid %llu", +- vi->nid); +- DBG_BUGON(1); +- return -EFSCORRUPTED; +- } + memcpy(lnk, kaddr + m_pofs, inode->i_size); + lnk[inode->i_size] = '\0'; + +diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c +index d6fe002a4a7194..2535479fb82dbe 100644 +--- a/fs/erofs/zdata.c ++++ b/fs/erofs/zdata.c +@@ -19,10 +19,7 @@ + typedef void *z_erofs_next_pcluster_t; + + struct z_erofs_bvec { +- union { +- struct page *page; +- struct folio *folio; +- }; ++ struct page *page; + int offset; + unsigned int end; + }; +@@ -617,32 +614,31 @@ static void z_erofs_bind_cache(struct z_erofs_decompress_frontend *fe) + fe->mode = Z_EROFS_PCLUSTER_FOLLOWED_NOINPLACE; + } + +-/* called by erofs_shrinker to get rid of all cached compressed bvecs */ ++/* (erofs_shrinker) disconnect cached encoded data with pclusters */ + int erofs_try_to_free_all_cached_folios(struct erofs_sb_info *sbi, + struct erofs_workgroup *grp) + { + struct z_erofs_pcluster *const pcl = + container_of(grp, struct z_erofs_pcluster, obj); + unsigned int pclusterpages = z_erofs_pclusterpages(pcl); ++ struct folio *folio; + int i; + + DBG_BUGON(z_erofs_is_inline_pcluster(pcl)); +- /* There is no actice user since the pcluster is now freezed */ ++ /* Each cached folio contains one page unless bs > ps is supported */ + for (i = 0; i < pclusterpages; ++i) { +- struct folio *folio = pcl->compressed_bvecs[i].folio; ++ if (pcl->compressed_bvecs[i].page) { ++ folio = page_folio(pcl->compressed_bvecs[i].page); ++ /* Avoid reclaiming or migrating this folio */ ++ if (!folio_trylock(folio)) ++ return -EBUSY; + +- if (!folio) +- continue; +- +- /* Avoid reclaiming or migrating this folio */ +- if (!folio_trylock(folio)) +- return -EBUSY; +- +- if (!erofs_folio_is_managed(sbi, folio)) +- continue; +- pcl->compressed_bvecs[i].folio = NULL; +- folio_detach_private(folio); +- folio_unlock(folio); ++ if (!erofs_folio_is_managed(sbi, folio)) ++ continue; ++ pcl->compressed_bvecs[i].page = NULL; ++ folio_detach_private(folio); ++ folio_unlock(folio); ++ } + } + return 0; + } +@@ -650,9 +646,9 @@ int erofs_try_to_free_all_cached_folios(struct erofs_sb_info *sbi, + static bool z_erofs_cache_release_folio(struct folio *folio, gfp_t gfp) + { + struct z_erofs_pcluster *pcl = folio_get_private(folio); +- unsigned int pclusterpages = z_erofs_pclusterpages(pcl); ++ struct z_erofs_bvec *bvec = pcl->compressed_bvecs; ++ struct z_erofs_bvec *end = bvec + z_erofs_pclusterpages(pcl); + bool ret; +- int i; + + if (!folio_test_private(folio)) + return true; +@@ -661,9 +657,9 @@ static bool z_erofs_cache_release_folio(struct folio *folio, gfp_t gfp) + spin_lock(&pcl->obj.lockref.lock); + if (pcl->obj.lockref.count <= 0) { + DBG_BUGON(z_erofs_is_inline_pcluster(pcl)); +- for (i = 0; i < pclusterpages; ++i) { +- if (pcl->compressed_bvecs[i].folio == folio) { +- pcl->compressed_bvecs[i].folio = NULL; ++ for (; bvec < end; ++bvec) { ++ if (bvec->page && page_folio(bvec->page) == folio) { ++ bvec->page = NULL; + folio_detach_private(folio); + ret = true; + break; +@@ -1066,7 +1062,7 @@ static bool z_erofs_is_sync_decompress(struct erofs_sb_info *sbi, + + static bool z_erofs_page_is_invalidated(struct page *page) + { +- return !page->mapping && !z_erofs_is_shortlived_page(page); ++ return !page_folio(page)->mapping && !z_erofs_is_shortlived_page(page); + } + + struct z_erofs_decompress_backend { +@@ -1419,6 +1415,7 @@ static void z_erofs_fill_bio_vec(struct bio_vec *bvec, + bool tocache = false; + struct z_erofs_bvec zbv; + struct address_space *mapping; ++ struct folio *folio; + struct page *page; + int bs = i_blocksize(f->inode); + +@@ -1429,23 +1426,24 @@ static void z_erofs_fill_bio_vec(struct bio_vec *bvec, + spin_lock(&pcl->obj.lockref.lock); + zbv = pcl->compressed_bvecs[nr]; + spin_unlock(&pcl->obj.lockref.lock); +- if (!zbv.folio) ++ if (!zbv.page) + goto out_allocfolio; + +- bvec->bv_page = &zbv.folio->page; ++ bvec->bv_page = zbv.page; + DBG_BUGON(z_erofs_is_shortlived_page(bvec->bv_page)); ++ ++ folio = page_folio(zbv.page); + /* + * Handle preallocated cached folios. We tried to allocate such folios + * without triggering direct reclaim. If allocation failed, inplace + * file-backed folios will be used instead. + */ +- if (zbv.folio->private == (void *)Z_EROFS_PREALLOCATED_PAGE) { +- zbv.folio->private = 0; ++ if (folio->private == (void *)Z_EROFS_PREALLOCATED_PAGE) { + tocache = true; + goto out_tocache; + } + +- mapping = READ_ONCE(zbv.folio->mapping); ++ mapping = READ_ONCE(folio->mapping); + /* + * File-backed folios for inplace I/Os are all locked steady, + * therefore it is impossible for `mapping` to be NULL. +@@ -1457,56 +1455,58 @@ static void z_erofs_fill_bio_vec(struct bio_vec *bvec, + return; + } + +- folio_lock(zbv.folio); +- if (zbv.folio->mapping == mc) { ++ folio_lock(folio); ++ if (likely(folio->mapping == mc)) { + /* + * The cached folio is still in managed cache but without + * a valid `->private` pcluster hint. Let's reconnect them. + */ +- if (!folio_test_private(zbv.folio)) { +- folio_attach_private(zbv.folio, pcl); ++ if (!folio_test_private(folio)) { ++ folio_attach_private(folio, pcl); + /* compressed_bvecs[] already takes a ref before */ +- folio_put(zbv.folio); ++ folio_put(folio); + } +- +- /* no need to submit if it is already up-to-date */ +- if (folio_test_uptodate(zbv.folio)) { +- folio_unlock(zbv.folio); +- bvec->bv_page = NULL; ++ if (likely(folio->private == pcl)) { ++ /* don't submit cache I/Os again if already uptodate */ ++ if (folio_test_uptodate(folio)) { ++ folio_unlock(folio); ++ bvec->bv_page = NULL; ++ } ++ return; + } +- return; ++ /* ++ * Already linked with another pcluster, which only appears in ++ * crafted images by fuzzers for now. But handle this anyway. ++ */ ++ tocache = false; /* use temporary short-lived pages */ ++ } else { ++ DBG_BUGON(1); /* referenced managed folios can't be truncated */ ++ tocache = true; + } +- +- /* +- * It has been truncated, so it's unsafe to reuse this one. Let's +- * allocate a new page for compressed data. +- */ +- DBG_BUGON(zbv.folio->mapping); +- tocache = true; +- folio_unlock(zbv.folio); +- folio_put(zbv.folio); ++ folio_unlock(folio); ++ folio_put(folio); + out_allocfolio: + page = erofs_allocpage(&f->pagepool, gfp | __GFP_NOFAIL); + spin_lock(&pcl->obj.lockref.lock); +- if (pcl->compressed_bvecs[nr].folio) { ++ if (unlikely(pcl->compressed_bvecs[nr].page != zbv.page)) { + erofs_pagepool_add(&f->pagepool, page); + spin_unlock(&pcl->obj.lockref.lock); + cond_resched(); + goto repeat; + } +- pcl->compressed_bvecs[nr].folio = zbv.folio = page_folio(page); ++ bvec->bv_page = pcl->compressed_bvecs[nr].page = page; ++ folio = page_folio(page); + spin_unlock(&pcl->obj.lockref.lock); +- bvec->bv_page = page; + out_tocache: + if (!tocache || bs != PAGE_SIZE || +- filemap_add_folio(mc, zbv.folio, pcl->obj.index + nr, gfp)) { ++ filemap_add_folio(mc, folio, pcl->obj.index + nr, gfp)) { + /* turn into a temporary shortlived folio (1 ref) */ +- zbv.folio->private = (void *)Z_EROFS_SHORTLIVED_PAGE; ++ folio->private = (void *)Z_EROFS_SHORTLIVED_PAGE; + return; + } +- folio_attach_private(zbv.folio, pcl); ++ folio_attach_private(folio, pcl); + /* drop a refcount added by allocpage (then 2 refs in total here) */ +- folio_put(zbv.folio); ++ folio_put(folio); + } + + static struct z_erofs_decompressqueue *jobqueue_init(struct super_block *sb, +@@ -1638,13 +1638,10 @@ static void z_erofs_submit_queue(struct z_erofs_decompress_frontend *f, + cur = mdev.m_pa; + end = cur + pcl->pclustersize; + do { +- z_erofs_fill_bio_vec(&bvec, f, pcl, i++, mc); +- if (!bvec.bv_page) +- continue; +- ++ bvec.bv_page = NULL; + if (bio && (cur != last_pa || + bio->bi_bdev != mdev.m_bdev)) { +-io_retry: ++drain_io: + if (!erofs_is_fscache_mode(sb)) + submit_bio(bio); + else +@@ -1657,6 +1654,15 @@ static void z_erofs_submit_queue(struct z_erofs_decompress_frontend *f, + bio = NULL; + } + ++ if (!bvec.bv_page) { ++ z_erofs_fill_bio_vec(&bvec, f, pcl, i++, mc); ++ if (!bvec.bv_page) ++ continue; ++ if (cur + bvec.bv_len > end) ++ bvec.bv_len = end - cur; ++ DBG_BUGON(bvec.bv_len < sb->s_blocksize); ++ } ++ + if (unlikely(PageWorkingset(bvec.bv_page)) && + !memstall) { + psi_memstall_enter(&pflags); +@@ -1676,13 +1682,9 @@ static void z_erofs_submit_queue(struct z_erofs_decompress_frontend *f, + ++nr_bios; + } + +- if (cur + bvec.bv_len > end) +- bvec.bv_len = end - cur; +- DBG_BUGON(bvec.bv_len < sb->s_blocksize); + if (!bio_add_page(bio, bvec.bv_page, bvec.bv_len, + bvec.bv_offset)) +- goto io_retry; +- ++ goto drain_io; + last_pa = cur + bvec.bv_len; + bypass = false; + } while ((cur += bvec.bv_len) < end); +diff --git a/fs/eventpoll.c b/fs/eventpoll.c +index f53ca4f7fceddd..6d0e2f547ae7d1 100644 +--- a/fs/eventpoll.c ++++ b/fs/eventpoll.c +@@ -420,7 +420,7 @@ static bool busy_loop_ep_timeout(unsigned long start_time, + + static bool ep_busy_loop_on(struct eventpoll *ep) + { +- return !!ep->busy_poll_usecs || net_busy_loop_on(); ++ return !!READ_ONCE(ep->busy_poll_usecs) || net_busy_loop_on(); + } + + static bool ep_busy_loop_end(void *p, unsigned long start_time) +diff --git a/fs/exfat/nls.c b/fs/exfat/nls.c +index afdf13c34ff526..1ac011088ce76e 100644 +--- a/fs/exfat/nls.c ++++ b/fs/exfat/nls.c +@@ -779,8 +779,11 @@ int exfat_create_upcase_table(struct super_block *sb) + le32_to_cpu(ep->dentry.upcase.checksum)); + + brelse(bh); +- if (ret && ret != -EIO) ++ if (ret && ret != -EIO) { ++ /* free memory from exfat_load_upcase_table call */ ++ exfat_free_upcase_table(sbi); + goto load_default; ++ } + + /* load successfully */ + return ret; +diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c +index e9bbb1da2d0a24..5a3b4bc1241499 100644 +--- a/fs/ext4/ialloc.c ++++ b/fs/ext4/ialloc.c +@@ -514,6 +514,8 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, + if (min_inodes < 1) + min_inodes = 1; + min_clusters = avefreec - EXT4_CLUSTERS_PER_GROUP(sb)*flex_size / 4; ++ if (min_clusters < 0) ++ min_clusters = 0; + + /* + * Start looking in the flex group where we last allocated an +@@ -755,10 +757,10 @@ int ext4_mark_inode_used(struct super_block *sb, int ino) + struct ext4_group_desc *gdp; + ext4_group_t group; + int bit; +- int err = -EFSCORRUPTED; ++ int err; + + if (ino < EXT4_FIRST_INO(sb) || ino > max_ino) +- goto out; ++ return -EFSCORRUPTED; + + group = (ino - 1) / EXT4_INODES_PER_GROUP(sb); + bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb); +@@ -860,6 +862,7 @@ int ext4_mark_inode_used(struct super_block *sb, int ino) + err = ext4_handle_dirty_metadata(NULL, NULL, group_desc_bh); + sync_dirty_buffer(group_desc_bh); + out: ++ brelse(inode_bitmap_bh); + return err; + } + +@@ -1053,12 +1056,13 @@ struct inode *__ext4_new_inode(struct mnt_idmap *idmap, + brelse(inode_bitmap_bh); + inode_bitmap_bh = ext4_read_inode_bitmap(sb, group); + /* Skip groups with suspicious inode tables */ +- if (((!(sbi->s_mount_state & EXT4_FC_REPLAY)) +- && EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) || +- IS_ERR(inode_bitmap_bh)) { ++ if (IS_ERR(inode_bitmap_bh)) { + inode_bitmap_bh = NULL; + goto next_group; + } ++ if (!(sbi->s_mount_state & EXT4_FC_REPLAY) && ++ EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) ++ goto next_group; + + repeat_in_this_group: + ret2 = find_inode_bit(sb, group, inode_bitmap_bh, &ino); +diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c +index e7a09a99837b96..44a5f6df59ecda 100644 +--- a/fs/ext4/inline.c ++++ b/fs/ext4/inline.c +@@ -1664,24 +1664,36 @@ struct buffer_head *ext4_find_inline_entry(struct inode *dir, + struct ext4_dir_entry_2 **res_dir, + int *has_inline_data) + { ++ struct ext4_xattr_ibody_find is = { ++ .s = { .not_found = -ENODATA, }, ++ }; ++ struct ext4_xattr_info i = { ++ .name_index = EXT4_XATTR_INDEX_SYSTEM, ++ .name = EXT4_XATTR_SYSTEM_DATA, ++ }; + int ret; +- struct ext4_iloc iloc; + void *inline_start; + int inline_size; + +- if (ext4_get_inode_loc(dir, &iloc)) +- return NULL; ++ ret = ext4_get_inode_loc(dir, &is.iloc); ++ if (ret) ++ return ERR_PTR(ret); + + down_read(&EXT4_I(dir)->xattr_sem); ++ ++ ret = ext4_xattr_ibody_find(dir, &i, &is); ++ if (ret) ++ goto out; ++ + if (!ext4_has_inline_data(dir)) { + *has_inline_data = 0; + goto out; + } + +- inline_start = (void *)ext4_raw_inode(&iloc)->i_block + ++ inline_start = (void *)ext4_raw_inode(&is.iloc)->i_block + + EXT4_INLINE_DOTDOT_SIZE; + inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE; +- ret = ext4_search_dir(iloc.bh, inline_start, inline_size, ++ ret = ext4_search_dir(is.iloc.bh, inline_start, inline_size, + dir, fname, 0, res_dir); + if (ret == 1) + goto out_find; +@@ -1691,20 +1703,23 @@ struct buffer_head *ext4_find_inline_entry(struct inode *dir, + if (ext4_get_inline_size(dir) == EXT4_MIN_INLINE_DATA_SIZE) + goto out; + +- inline_start = ext4_get_inline_xattr_pos(dir, &iloc); ++ inline_start = ext4_get_inline_xattr_pos(dir, &is.iloc); + inline_size = ext4_get_inline_size(dir) - EXT4_MIN_INLINE_DATA_SIZE; + +- ret = ext4_search_dir(iloc.bh, inline_start, inline_size, ++ ret = ext4_search_dir(is.iloc.bh, inline_start, inline_size, + dir, fname, 0, res_dir); + if (ret == 1) + goto out_find; + + out: +- brelse(iloc.bh); +- iloc.bh = NULL; ++ brelse(is.iloc.bh); ++ if (ret < 0) ++ is.iloc.bh = ERR_PTR(ret); ++ else ++ is.iloc.bh = NULL; + out_find: + up_read(&EXT4_I(dir)->xattr_sem); +- return iloc.bh; ++ return is.iloc.bh; + } + + int ext4_delete_inline_entry(handle_t *handle, +diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c +index 9dda9cd68ab2f5..dfecd25cee4eae 100644 +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -3887,11 +3887,8 @@ static void ext4_free_data_in_buddy(struct super_block *sb, + /* + * Clear the trimmed flag for the group so that the next + * ext4_trim_fs can trim it. +- * If the volume is mounted with -o discard, online discard +- * is supported and the free blocks will be trimmed online. + */ +- if (!test_opt(sb, DISCARD)) +- EXT4_MB_GRP_CLEAR_TRIMMED(db); ++ EXT4_MB_GRP_CLEAR_TRIMMED(db); + + if (!db->bb_free_root.rb_node) { + /* No more items in the per group rb tree +@@ -6515,8 +6512,9 @@ static void ext4_mb_clear_bb(handle_t *handle, struct inode *inode, + " group:%u block:%d count:%lu failed" + " with %d", block_group, bit, count, + err); +- } else +- EXT4_MB_GRP_CLEAR_TRIMMED(e4b.bd_info); ++ } ++ ++ EXT4_MB_GRP_CLEAR_TRIMMED(e4b.bd_info); + + ext4_lock_group(sb, block_group); + mb_free_blocks(inode, &e4b, bit, count_clusters); +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index c682fb927b64b8..edc692984404d5 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -5177,6 +5177,18 @@ static int ext4_block_group_meta_init(struct super_block *sb, int silent) + return 0; + } + ++/* ++ * It's hard to get stripe aligned blocks if stripe is not aligned with ++ * cluster, just disable stripe and alert user to simplify code and avoid ++ * stripe aligned allocation which will rarely succeed. ++ */ ++static bool ext4_is_stripe_incompatible(struct super_block *sb, unsigned long stripe) ++{ ++ struct ext4_sb_info *sbi = EXT4_SB(sb); ++ return (stripe > 0 && sbi->s_cluster_ratio > 1 && ++ stripe % sbi->s_cluster_ratio != 0); ++} ++ + static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) + { + struct ext4_super_block *es = NULL; +@@ -5284,13 +5296,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) + goto failed_mount3; + + sbi->s_stripe = ext4_get_stripe_size(sbi); +- /* +- * It's hard to get stripe aligned blocks if stripe is not aligned with +- * cluster, just disable stripe and alert user to simpfy code and avoid +- * stripe aligned allocation which will rarely successes. +- */ +- if (sbi->s_stripe > 0 && sbi->s_cluster_ratio > 1 && +- sbi->s_stripe % sbi->s_cluster_ratio != 0) { ++ if (ext4_is_stripe_incompatible(sb, sbi->s_stripe)) { + ext4_msg(sb, KERN_WARNING, + "stripe (%lu) is not aligned with cluster size (%u), " + "stripe is disabled", +@@ -6453,6 +6459,15 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb) + + } + ++ if ((ctx->spec & EXT4_SPEC_s_stripe) && ++ ext4_is_stripe_incompatible(sb, ctx->s_stripe)) { ++ ext4_msg(sb, KERN_WARNING, ++ "stripe (%lu) is not aligned with cluster size (%u), " ++ "stripe is disabled", ++ ctx->s_stripe, sbi->s_cluster_ratio); ++ ctx->s_stripe = 0; ++ } ++ + /* + * Changing the DIOREAD_NOLOCK or DELALLOC mount options may cause + * two calls to ext4_should_dioread_nolock() to return inconsistent +diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c +index 1ef82a5463910e..b0506745adab7a 100644 +--- a/fs/f2fs/compress.c ++++ b/fs/f2fs/compress.c +@@ -945,7 +945,7 @@ static int __f2fs_get_cluster_blocks(struct inode *inode, + unsigned int cluster_size = F2FS_I(inode)->i_cluster_size; + int count, i; + +- for (i = 1, count = 1; i < cluster_size; i++) { ++ for (i = 0, count = 0; i < cluster_size; i++) { + block_t blkaddr = data_blkaddr(dn->inode, dn->node_page, + dn->ofs_in_node + i); + +@@ -956,8 +956,8 @@ static int __f2fs_get_cluster_blocks(struct inode *inode, + return count; + } + +-static int __f2fs_cluster_blocks(struct inode *inode, +- unsigned int cluster_idx, bool compr_blks) ++static int __f2fs_cluster_blocks(struct inode *inode, unsigned int cluster_idx, ++ enum cluster_check_type type) + { + struct dnode_of_data dn; + unsigned int start_idx = cluster_idx << +@@ -978,10 +978,12 @@ static int __f2fs_cluster_blocks(struct inode *inode, + } + + if (dn.data_blkaddr == COMPRESS_ADDR) { +- if (compr_blks) +- ret = __f2fs_get_cluster_blocks(inode, &dn); +- else ++ if (type == CLUSTER_COMPR_BLKS) ++ ret = 1 + __f2fs_get_cluster_blocks(inode, &dn); ++ else if (type == CLUSTER_IS_COMPR) + ret = 1; ++ } else if (type == CLUSTER_RAW_BLKS) { ++ ret = __f2fs_get_cluster_blocks(inode, &dn); + } + fail: + f2fs_put_dnode(&dn); +@@ -991,7 +993,16 @@ static int __f2fs_cluster_blocks(struct inode *inode, + /* return # of compressed blocks in compressed cluster */ + static int f2fs_compressed_blocks(struct compress_ctx *cc) + { +- return __f2fs_cluster_blocks(cc->inode, cc->cluster_idx, true); ++ return __f2fs_cluster_blocks(cc->inode, cc->cluster_idx, ++ CLUSTER_COMPR_BLKS); ++} ++ ++/* return # of raw blocks in non-compressed cluster */ ++static int f2fs_decompressed_blocks(struct inode *inode, ++ unsigned int cluster_idx) ++{ ++ return __f2fs_cluster_blocks(inode, cluster_idx, ++ CLUSTER_RAW_BLKS); + } + + /* return whether cluster is compressed one or not */ +@@ -999,7 +1010,16 @@ int f2fs_is_compressed_cluster(struct inode *inode, pgoff_t index) + { + return __f2fs_cluster_blocks(inode, + index >> F2FS_I(inode)->i_log_cluster_size, +- false); ++ CLUSTER_IS_COMPR); ++} ++ ++/* return whether cluster contains non raw blocks or not */ ++bool f2fs_is_sparse_cluster(struct inode *inode, pgoff_t index) ++{ ++ unsigned int cluster_idx = index >> F2FS_I(inode)->i_log_cluster_size; ++ ++ return f2fs_decompressed_blocks(inode, cluster_idx) != ++ F2FS_I(inode)->i_cluster_size; + } + + static bool cluster_may_compress(struct compress_ctx *cc) +diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c +index 467f67cf2b3800..825f6bcb7fc2ee 100644 +--- a/fs/f2fs/data.c ++++ b/fs/f2fs/data.c +@@ -2645,10 +2645,13 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) + struct dnode_of_data dn; + struct node_info ni; + bool ipu_force = false; ++ bool atomic_commit; + int err = 0; + + /* Use COW inode to make dnode_of_data for atomic write */ +- if (f2fs_is_atomic_file(inode)) ++ atomic_commit = f2fs_is_atomic_file(inode) && ++ page_private_atomic(fio->page); ++ if (atomic_commit) + set_new_dnode(&dn, F2FS_I(inode)->cow_inode, NULL, NULL, 0); + else + set_new_dnode(&dn, inode, NULL, NULL, 0); +@@ -2747,6 +2750,8 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) + f2fs_outplace_write_data(&dn, fio); + trace_f2fs_do_write_data_page(page_folio(page), OPU); + set_inode_flag(inode, FI_APPEND_WRITE); ++ if (atomic_commit) ++ clear_page_private_atomic(page); + out_writepage: + f2fs_put_dnode(&dn); + out: +@@ -3716,6 +3721,9 @@ static int f2fs_write_end(struct file *file, + + set_page_dirty(page); + ++ if (f2fs_is_atomic_file(inode)) ++ set_page_private_atomic(page); ++ + if (pos + copied > i_size_read(inode) && + !f2fs_verity_in_progress(inode)) { + f2fs_i_size_write(inode, pos + copied); +diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c +index 02c9355176d3b5..5a00e010f8c112 100644 +--- a/fs/f2fs/dir.c ++++ b/fs/f2fs/dir.c +@@ -157,7 +157,8 @@ static unsigned long dir_block_index(unsigned int level, + unsigned long bidx = 0; + + for (i = 0; i < level; i++) +- bidx += dir_buckets(i, dir_level) * bucket_blocks(i); ++ bidx += mul_u32_u32(dir_buckets(i, dir_level), ++ bucket_blocks(i)); + bidx += idx * bucket_blocks(level); + return bidx; + } +diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c +index fd1fc06359eea3..62ac440d94168a 100644 +--- a/fs/f2fs/extent_cache.c ++++ b/fs/f2fs/extent_cache.c +@@ -366,7 +366,7 @@ static unsigned int __free_extent_tree(struct f2fs_sb_info *sbi, + static void __drop_largest_extent(struct extent_tree *et, + pgoff_t fofs, unsigned int len) + { +- if (fofs < et->largest.fofs + et->largest.len && ++ if (fofs < (pgoff_t)et->largest.fofs + et->largest.len && + fofs + len > et->largest.fofs) { + et->largest.len = 0; + et->largest_updated = true; +@@ -456,7 +456,7 @@ static bool __lookup_extent_tree(struct inode *inode, pgoff_t pgofs, + + if (type == EX_READ && + et->largest.fofs <= pgofs && +- et->largest.fofs + et->largest.len > pgofs) { ++ (pgoff_t)et->largest.fofs + et->largest.len > pgofs) { + *ei = et->largest; + ret = true; + stat_inc_largest_node_hit(sbi); +diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h +index 92fda31c68cdc3..9c8acb98f4dbf6 100644 +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -285,6 +285,7 @@ enum { + APPEND_INO, /* for append ino list */ + UPDATE_INO, /* for update ino list */ + TRANS_DIR_INO, /* for transactions dir ino list */ ++ XATTR_DIR_INO, /* for xattr updated dir ino list */ + FLUSH_INO, /* for multiple device flushing */ + MAX_INO_ENTRY, /* max. list */ + }; +@@ -784,7 +785,6 @@ enum { + FI_NEED_IPU, /* used for ipu per file */ + FI_ATOMIC_FILE, /* indicate atomic file */ + FI_DATA_EXIST, /* indicate data exists */ +- FI_INLINE_DOTS, /* indicate inline dot dentries */ + FI_SKIP_WRITES, /* should skip data page writeback */ + FI_OPU_WRITE, /* used for opu per file */ + FI_DIRTY_FILE, /* indicate regular/symlink has dirty pages */ +@@ -802,6 +802,7 @@ enum { + FI_ALIGNED_WRITE, /* enable aligned write */ + FI_COW_FILE, /* indicate COW file */ + FI_ATOMIC_COMMITTED, /* indicate atomic commit completed except disk sync */ ++ FI_ATOMIC_DIRTIED, /* indicate atomic file is dirtied */ + FI_ATOMIC_REPLACE, /* indicate atomic replace */ + FI_OPENED_FILE, /* indicate file has been opened */ + FI_MAX, /* max flag, never be used */ +@@ -1155,6 +1156,7 @@ enum cp_reason_type { + CP_FASTBOOT_MODE, + CP_SPEC_LOG_NUM, + CP_RECOVER_DIR, ++ CP_XATTR_DIR, + }; + + enum iostat_type { +@@ -1418,7 +1420,8 @@ static inline void f2fs_clear_bit(unsigned int nr, char *addr); + * bit 1 PAGE_PRIVATE_ONGOING_MIGRATION + * bit 2 PAGE_PRIVATE_INLINE_INODE + * bit 3 PAGE_PRIVATE_REF_RESOURCE +- * bit 4- f2fs private data ++ * bit 4 PAGE_PRIVATE_ATOMIC_WRITE ++ * bit 5- f2fs private data + * + * Layout B: lowest bit should be 0 + * page.private is a wrapped pointer. +@@ -1428,6 +1431,7 @@ enum { + PAGE_PRIVATE_ONGOING_MIGRATION, /* data page which is on-going migrating */ + PAGE_PRIVATE_INLINE_INODE, /* inode page contains inline data */ + PAGE_PRIVATE_REF_RESOURCE, /* dirty page has referenced resources */ ++ PAGE_PRIVATE_ATOMIC_WRITE, /* data page from atomic write path */ + PAGE_PRIVATE_MAX + }; + +@@ -2396,14 +2400,17 @@ static inline void clear_page_private_##name(struct page *page) \ + PAGE_PRIVATE_GET_FUNC(nonpointer, NOT_POINTER); + PAGE_PRIVATE_GET_FUNC(inline, INLINE_INODE); + PAGE_PRIVATE_GET_FUNC(gcing, ONGOING_MIGRATION); ++PAGE_PRIVATE_GET_FUNC(atomic, ATOMIC_WRITE); + + PAGE_PRIVATE_SET_FUNC(reference, REF_RESOURCE); + PAGE_PRIVATE_SET_FUNC(inline, INLINE_INODE); + PAGE_PRIVATE_SET_FUNC(gcing, ONGOING_MIGRATION); ++PAGE_PRIVATE_SET_FUNC(atomic, ATOMIC_WRITE); + + PAGE_PRIVATE_CLEAR_FUNC(reference, REF_RESOURCE); + PAGE_PRIVATE_CLEAR_FUNC(inline, INLINE_INODE); + PAGE_PRIVATE_CLEAR_FUNC(gcing, ONGOING_MIGRATION); ++PAGE_PRIVATE_CLEAR_FUNC(atomic, ATOMIC_WRITE); + + static inline unsigned long get_page_private_data(struct page *page) + { +@@ -2435,6 +2442,7 @@ static inline void clear_page_private_all(struct page *page) + clear_page_private_reference(page); + clear_page_private_gcing(page); + clear_page_private_inline(page); ++ clear_page_private_atomic(page); + + f2fs_bug_on(F2FS_P_SB(page), page_private(page)); + } +@@ -3038,10 +3046,8 @@ static inline void __mark_inode_dirty_flag(struct inode *inode, + return; + fallthrough; + case FI_DATA_EXIST: +- case FI_INLINE_DOTS: + case FI_PIN_FILE: + case FI_COMPRESS_RELEASED: +- case FI_ATOMIC_COMMITTED: + f2fs_mark_inode_dirty_sync(inode, true); + } + } +@@ -3163,8 +3169,6 @@ static inline void get_inline_info(struct inode *inode, struct f2fs_inode *ri) + set_bit(FI_INLINE_DENTRY, fi->flags); + if (ri->i_inline & F2FS_DATA_EXIST) + set_bit(FI_DATA_EXIST, fi->flags); +- if (ri->i_inline & F2FS_INLINE_DOTS) +- set_bit(FI_INLINE_DOTS, fi->flags); + if (ri->i_inline & F2FS_EXTRA_ATTR) + set_bit(FI_EXTRA_ATTR, fi->flags); + if (ri->i_inline & F2FS_PIN_FILE) +@@ -3185,8 +3189,6 @@ static inline void set_raw_inline(struct inode *inode, struct f2fs_inode *ri) + ri->i_inline |= F2FS_INLINE_DENTRY; + if (is_inode_flag_set(inode, FI_DATA_EXIST)) + ri->i_inline |= F2FS_DATA_EXIST; +- if (is_inode_flag_set(inode, FI_INLINE_DOTS)) +- ri->i_inline |= F2FS_INLINE_DOTS; + if (is_inode_flag_set(inode, FI_EXTRA_ATTR)) + ri->i_inline |= F2FS_EXTRA_ATTR; + if (is_inode_flag_set(inode, FI_PIN_FILE)) +@@ -3273,11 +3275,6 @@ static inline int f2fs_exist_data(struct inode *inode) + return is_inode_flag_set(inode, FI_DATA_EXIST); + } + +-static inline int f2fs_has_inline_dots(struct inode *inode) +-{ +- return is_inode_flag_set(inode, FI_INLINE_DOTS); +-} +- + static inline int f2fs_is_mmap_file(struct inode *inode) + { + return is_inode_flag_set(inode, FI_MMAP_FILE); +@@ -3501,7 +3498,7 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry, + int f2fs_truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end); + void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count); + int f2fs_do_shutdown(struct f2fs_sb_info *sbi, unsigned int flag, +- bool readonly); ++ bool readonly, bool need_lock); + int f2fs_precache_extents(struct inode *inode); + int f2fs_fileattr_get(struct dentry *dentry, struct fileattr *fa); + int f2fs_fileattr_set(struct mnt_idmap *idmap, +@@ -4280,6 +4277,11 @@ static inline bool f2fs_meta_inode_gc_required(struct inode *inode) + * compress.c + */ + #ifdef CONFIG_F2FS_FS_COMPRESSION ++enum cluster_check_type { ++ CLUSTER_IS_COMPR, /* check only if compressed cluster */ ++ CLUSTER_COMPR_BLKS, /* return # of compressed blocks in a cluster */ ++ CLUSTER_RAW_BLKS /* return # of raw blocks in a cluster */ ++}; + bool f2fs_is_compressed_page(struct page *page); + struct page *f2fs_compress_control_page(struct page *page); + int f2fs_prepare_compress_overwrite(struct inode *inode, +@@ -4306,6 +4308,7 @@ int f2fs_write_multi_pages(struct compress_ctx *cc, + struct writeback_control *wbc, + enum iostat_type io_type); + int f2fs_is_compressed_cluster(struct inode *inode, pgoff_t index); ++bool f2fs_is_sparse_cluster(struct inode *inode, pgoff_t index); + void f2fs_update_read_extent_tree_range_compressed(struct inode *inode, + pgoff_t fofs, block_t blkaddr, + unsigned int llen, unsigned int c_len); +@@ -4392,6 +4395,12 @@ static inline bool f2fs_load_compressed_page(struct f2fs_sb_info *sbi, + static inline void f2fs_invalidate_compress_pages(struct f2fs_sb_info *sbi, + nid_t ino) { } + #define inc_compr_inode_stat(inode) do { } while (0) ++static inline int f2fs_is_compressed_cluster( ++ struct inode *inode, ++ pgoff_t index) { return 0; } ++static inline bool f2fs_is_sparse_cluster( ++ struct inode *inode, ++ pgoff_t index) { return true; } + static inline void f2fs_update_read_extent_tree_range_compressed( + struct inode *inode, + pgoff_t fofs, block_t blkaddr, +diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c +index 387ce167dda1b4..4bee980c6d1862 100644 +--- a/fs/f2fs/file.c ++++ b/fs/f2fs/file.c +@@ -218,6 +218,9 @@ static inline enum cp_reason_type need_do_checkpoint(struct inode *inode) + f2fs_exist_written_data(sbi, F2FS_I(inode)->i_pino, + TRANS_DIR_INO)) + cp_reason = CP_RECOVER_DIR; ++ else if (f2fs_exist_written_data(sbi, F2FS_I(inode)->i_pino, ++ XATTR_DIR_INO)) ++ cp_reason = CP_XATTR_DIR; + + return cp_reason; + } +@@ -2117,10 +2120,12 @@ static int f2fs_ioc_start_atomic_write(struct file *filp, bool truncate) + struct mnt_idmap *idmap = file_mnt_idmap(filp); + struct f2fs_inode_info *fi = F2FS_I(inode); + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); +- struct inode *pinode; + loff_t isize; + int ret; + ++ if (!(filp->f_mode & FMODE_WRITE)) ++ return -EBADF; ++ + if (!inode_owner_or_capable(idmap, inode)) + return -EACCES; + +@@ -2167,15 +2172,10 @@ static int f2fs_ioc_start_atomic_write(struct file *filp, bool truncate) + /* Check if the inode already has a COW inode */ + if (fi->cow_inode == NULL) { + /* Create a COW inode for atomic write */ +- pinode = f2fs_iget(inode->i_sb, fi->i_pino); +- if (IS_ERR(pinode)) { +- f2fs_up_write(&fi->i_gc_rwsem[WRITE]); +- ret = PTR_ERR(pinode); +- goto out; +- } ++ struct dentry *dentry = file_dentry(filp); ++ struct inode *dir = d_inode(dentry->d_parent); + +- ret = f2fs_get_tmpfile(idmap, pinode, &fi->cow_inode); +- iput(pinode); ++ ret = f2fs_get_tmpfile(idmap, dir, &fi->cow_inode); + if (ret) { + f2fs_up_write(&fi->i_gc_rwsem[WRITE]); + goto out; +@@ -2188,6 +2188,10 @@ static int f2fs_ioc_start_atomic_write(struct file *filp, bool truncate) + F2FS_I(fi->cow_inode)->atomic_inode = inode; + } else { + /* Reuse the already created COW inode */ ++ f2fs_bug_on(sbi, get_dirty_pages(fi->cow_inode)); ++ ++ invalidate_mapping_pages(fi->cow_inode->i_mapping, 0, -1); ++ + ret = f2fs_do_truncate_blocks(fi->cow_inode, 0, true); + if (ret) { + f2fs_up_write(&fi->i_gc_rwsem[WRITE]); +@@ -2229,6 +2233,9 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp) + struct mnt_idmap *idmap = file_mnt_idmap(filp); + int ret; + ++ if (!(filp->f_mode & FMODE_WRITE)) ++ return -EBADF; ++ + if (!inode_owner_or_capable(idmap, inode)) + return -EACCES; + +@@ -2261,6 +2268,9 @@ static int f2fs_ioc_abort_atomic_write(struct file *filp) + struct mnt_idmap *idmap = file_mnt_idmap(filp); + int ret; + ++ if (!(filp->f_mode & FMODE_WRITE)) ++ return -EBADF; ++ + if (!inode_owner_or_capable(idmap, inode)) + return -EACCES; + +@@ -2280,7 +2290,7 @@ static int f2fs_ioc_abort_atomic_write(struct file *filp) + } + + int f2fs_do_shutdown(struct f2fs_sb_info *sbi, unsigned int flag, +- bool readonly) ++ bool readonly, bool need_lock) + { + struct super_block *sb = sbi->sb; + int ret = 0; +@@ -2327,12 +2337,19 @@ int f2fs_do_shutdown(struct f2fs_sb_info *sbi, unsigned int flag, + if (readonly) + goto out; + ++ /* grab sb->s_umount to avoid racing w/ remount() */ ++ if (need_lock) ++ down_read(&sbi->sb->s_umount); ++ + f2fs_stop_gc_thread(sbi); + f2fs_stop_discard_thread(sbi); + + f2fs_drop_discard_cmd(sbi); + clear_opt(sbi, DISCARD); + ++ if (need_lock) ++ up_read(&sbi->sb->s_umount); ++ + f2fs_update_time(sbi, REQ_TIME); + out: + +@@ -2369,7 +2386,7 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) + } + } + +- ret = f2fs_do_shutdown(sbi, in, readonly); ++ ret = f2fs_do_shutdown(sbi, in, readonly, true); + + if (need_drop) + mnt_drop_write_file(filp); +@@ -2687,7 +2704,8 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi, + (range->start + range->len) >> PAGE_SHIFT, + DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE)); + +- if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) { ++ if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED) || ++ f2fs_is_atomic_file(inode)) { + err = -EINVAL; + goto unlock_out; + } +@@ -2711,7 +2729,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi, + * block addresses are continuous. + */ + if (f2fs_lookup_read_extent_cache(inode, pg_start, &ei)) { +- if (ei.fofs + ei.len >= pg_end) ++ if ((pgoff_t)ei.fofs + ei.len >= pg_end) + goto out; + } + +@@ -2794,6 +2812,8 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi, + goto clear_out; + } + ++ f2fs_wait_on_page_writeback(page, DATA, true, true); ++ + set_page_dirty(page); + set_page_private_gcing(page); + f2fs_put_page(page, 1); +@@ -2918,6 +2938,11 @@ static int f2fs_move_file_range(struct file *file_in, loff_t pos_in, + goto out_unlock; + } + ++ if (f2fs_is_atomic_file(src) || f2fs_is_atomic_file(dst)) { ++ ret = -EINVAL; ++ goto out_unlock; ++ } ++ + ret = -EINVAL; + if (pos_in + len > src->i_size || pos_in + len < pos_in) + goto out_unlock; +@@ -3301,6 +3326,11 @@ static int f2fs_ioc_set_pin_file(struct file *filp, unsigned long arg) + + inode_lock(inode); + ++ if (f2fs_is_atomic_file(inode)) { ++ ret = -EINVAL; ++ goto out; ++ } ++ + if (!pin) { + clear_inode_flag(inode, FI_PIN_FILE); + f2fs_i_gc_failures_write(inode, 0); +@@ -4187,6 +4217,8 @@ static int redirty_blocks(struct inode *inode, pgoff_t page_idx, int len) + /* It will never fail, when page has pinned above */ + f2fs_bug_on(F2FS_I_SB(inode), !page); + ++ f2fs_wait_on_page_writeback(page, DATA, true, true); ++ + set_page_dirty(page); + set_page_private_gcing(page); + f2fs_put_page(page, 1); +@@ -4201,9 +4233,8 @@ static int f2fs_ioc_decompress_file(struct file *filp) + struct inode *inode = file_inode(filp); + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct f2fs_inode_info *fi = F2FS_I(inode); +- pgoff_t page_idx = 0, last_idx; +- int cluster_size = fi->i_cluster_size; +- int count, ret; ++ pgoff_t page_idx = 0, last_idx, cluster_idx; ++ int ret; + + if (!f2fs_sb_has_compression(sbi) || + F2FS_OPTION(sbi).compress_mode != COMPR_MODE_USER) +@@ -4236,10 +4267,15 @@ static int f2fs_ioc_decompress_file(struct file *filp) + goto out; + + last_idx = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); ++ last_idx >>= fi->i_log_cluster_size; ++ ++ for (cluster_idx = 0; cluster_idx < last_idx; cluster_idx++) { ++ page_idx = cluster_idx << fi->i_log_cluster_size; ++ ++ if (!f2fs_is_compressed_cluster(inode, page_idx)) ++ continue; + +- count = last_idx - page_idx; +- while (count && count >= cluster_size) { +- ret = redirty_blocks(inode, page_idx, cluster_size); ++ ret = redirty_blocks(inode, page_idx, fi->i_cluster_size); + if (ret < 0) + break; + +@@ -4249,9 +4285,6 @@ static int f2fs_ioc_decompress_file(struct file *filp) + break; + } + +- count -= cluster_size; +- page_idx += cluster_size; +- + cond_resched(); + if (fatal_signal_pending(current)) { + ret = -EINTR; +@@ -4278,9 +4311,9 @@ static int f2fs_ioc_compress_file(struct file *filp) + { + struct inode *inode = file_inode(filp); + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); +- pgoff_t page_idx = 0, last_idx; +- int cluster_size = F2FS_I(inode)->i_cluster_size; +- int count, ret; ++ struct f2fs_inode_info *fi = F2FS_I(inode); ++ pgoff_t page_idx = 0, last_idx, cluster_idx; ++ int ret; + + if (!f2fs_sb_has_compression(sbi) || + F2FS_OPTION(sbi).compress_mode != COMPR_MODE_USER) +@@ -4312,10 +4345,15 @@ static int f2fs_ioc_compress_file(struct file *filp) + set_inode_flag(inode, FI_ENABLE_COMPRESS); + + last_idx = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); ++ last_idx >>= fi->i_log_cluster_size; ++ ++ for (cluster_idx = 0; cluster_idx < last_idx; cluster_idx++) { ++ page_idx = cluster_idx << fi->i_log_cluster_size; + +- count = last_idx - page_idx; +- while (count && count >= cluster_size) { +- ret = redirty_blocks(inode, page_idx, cluster_size); ++ if (f2fs_is_sparse_cluster(inode, page_idx)) ++ continue; ++ ++ ret = redirty_blocks(inode, page_idx, fi->i_cluster_size); + if (ret < 0) + break; + +@@ -4325,9 +4363,6 @@ static int f2fs_ioc_compress_file(struct file *filp) + break; + } + +- count -= cluster_size; +- page_idx += cluster_size; +- + cond_resched(); + if (fatal_signal_pending(current)) { + ret = -EINTR; +@@ -4587,6 +4622,10 @@ static ssize_t f2fs_file_read_iter(struct kiocb *iocb, struct iov_iter *to) + f2fs_trace_rw_file_path(iocb->ki_filp, iocb->ki_pos, + iov_iter_count(to), READ); + ++ /* In LFS mode, if there is inflight dio, wait for its completion */ ++ if (f2fs_lfs_mode(F2FS_I_SB(inode))) ++ inode_dio_wait(inode); ++ + if (f2fs_should_use_dio(inode, iocb, to)) { + ret = f2fs_dio_read_iter(iocb, to); + } else { +diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c +index 57da02bfa823ef..0b23a0cb438fde 100644 +--- a/fs/f2fs/inode.c ++++ b/fs/f2fs/inode.c +@@ -35,6 +35,11 @@ void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync) + if (f2fs_inode_dirtied(inode, sync)) + return; + ++ if (f2fs_is_atomic_file(inode)) { ++ set_inode_flag(inode, FI_ATOMIC_DIRTIED); ++ return; ++ } ++ + mark_inode_dirty_sync(inode); + } + +diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c +index e54f8c08bda832..a2c4091fca6fac 100644 +--- a/fs/f2fs/namei.c ++++ b/fs/f2fs/namei.c +@@ -455,62 +455,6 @@ struct dentry *f2fs_get_parent(struct dentry *child) + return d_obtain_alias(f2fs_iget(child->d_sb, ino)); + } + +-static int __recover_dot_dentries(struct inode *dir, nid_t pino) +-{ +- struct f2fs_sb_info *sbi = F2FS_I_SB(dir); +- struct qstr dot = QSTR_INIT(".", 1); +- struct f2fs_dir_entry *de; +- struct page *page; +- int err = 0; +- +- if (f2fs_readonly(sbi->sb)) { +- f2fs_info(sbi, "skip recovering inline_dots inode (ino:%lu, pino:%u) in readonly mountpoint", +- dir->i_ino, pino); +- return 0; +- } +- +- if (!S_ISDIR(dir->i_mode)) { +- f2fs_err(sbi, "inconsistent inode status, skip recovering inline_dots inode (ino:%lu, i_mode:%u, pino:%u)", +- dir->i_ino, dir->i_mode, pino); +- set_sbi_flag(sbi, SBI_NEED_FSCK); +- return -ENOTDIR; +- } +- +- err = f2fs_dquot_initialize(dir); +- if (err) +- return err; +- +- f2fs_balance_fs(sbi, true); +- +- f2fs_lock_op(sbi); +- +- de = f2fs_find_entry(dir, &dot, &page); +- if (de) { +- f2fs_put_page(page, 0); +- } else if (IS_ERR(page)) { +- err = PTR_ERR(page); +- goto out; +- } else { +- err = f2fs_do_add_link(dir, &dot, NULL, dir->i_ino, S_IFDIR); +- if (err) +- goto out; +- } +- +- de = f2fs_find_entry(dir, &dotdot_name, &page); +- if (de) +- f2fs_put_page(page, 0); +- else if (IS_ERR(page)) +- err = PTR_ERR(page); +- else +- err = f2fs_do_add_link(dir, &dotdot_name, NULL, pino, S_IFDIR); +-out: +- if (!err) +- clear_inode_flag(dir, FI_INLINE_DOTS); +- +- f2fs_unlock_op(sbi); +- return err; +-} +- + static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry, + unsigned int flags) + { +@@ -520,7 +464,6 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry, + struct dentry *new; + nid_t ino = -1; + int err = 0; +- unsigned int root_ino = F2FS_ROOT_INO(F2FS_I_SB(dir)); + struct f2fs_filename fname; + + trace_f2fs_lookup_start(dir, dentry, flags); +@@ -556,17 +499,6 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry, + goto out; + } + +- if ((dir->i_ino == root_ino) && f2fs_has_inline_dots(dir)) { +- err = __recover_dot_dentries(dir, root_ino); +- if (err) +- goto out_iput; +- } +- +- if (f2fs_has_inline_dots(inode)) { +- err = __recover_dot_dentries(inode, dir->i_ino); +- if (err) +- goto out_iput; +- } + if (IS_ENCRYPTED(dir) && + (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) && + !fscrypt_has_permitted_context(dir, inode)) { +diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c +index 601825785226d2..425479d7692167 100644 +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -199,6 +199,10 @@ void f2fs_abort_atomic_write(struct inode *inode, bool clean) + clear_inode_flag(inode, FI_ATOMIC_COMMITTED); + clear_inode_flag(inode, FI_ATOMIC_REPLACE); + clear_inode_flag(inode, FI_ATOMIC_FILE); ++ if (is_inode_flag_set(inode, FI_ATOMIC_DIRTIED)) { ++ clear_inode_flag(inode, FI_ATOMIC_DIRTIED); ++ f2fs_mark_inode_dirty_sync(inode, true); ++ } + stat_dec_atomic_inode(inode); + + F2FS_I(inode)->atomic_write_task = NULL; +@@ -366,6 +370,10 @@ static int __f2fs_commit_atomic_write(struct inode *inode) + } else { + sbi->committed_atomic_block += fi->atomic_write_cnt; + set_inode_flag(inode, FI_ATOMIC_COMMITTED); ++ if (is_inode_flag_set(inode, FI_ATOMIC_DIRTIED)) { ++ clear_inode_flag(inode, FI_ATOMIC_DIRTIED); ++ f2fs_mark_inode_dirty_sync(inode, true); ++ } + } + + __complete_revoke_list(inode, &revoke_list, ret ? true : false); +@@ -1282,6 +1290,13 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi, + wait_list, issued); + return 0; + } ++ ++ /* ++ * Issue discard for conventional zones only if the device ++ * supports discard. ++ */ ++ if (!bdev_max_discard_sectors(bdev)) ++ return -EOPNOTSUPP; + } + #endif + +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index 1f1b3647a998c0..b4c8ac6c085989 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -2571,7 +2571,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) + + static void f2fs_shutdown(struct super_block *sb) + { +- f2fs_do_shutdown(F2FS_SB(sb), F2FS_GOING_DOWN_NOSYNC, false); ++ f2fs_do_shutdown(F2FS_SB(sb), F2FS_GOING_DOWN_NOSYNC, false, false); + } + + #ifdef CONFIG_QUOTA +@@ -3366,9 +3366,9 @@ static inline bool sanity_check_area_boundary(struct f2fs_sb_info *sbi, + u32 segment_count = le32_to_cpu(raw_super->segment_count); + u32 log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg); + u64 main_end_blkaddr = main_blkaddr + +- (segment_count_main << log_blocks_per_seg); ++ ((u64)segment_count_main << log_blocks_per_seg); + u64 seg_end_blkaddr = segment0_blkaddr + +- (segment_count << log_blocks_per_seg); ++ ((u64)segment_count << log_blocks_per_seg); + + if (segment0_blkaddr != cp_blkaddr) { + f2fs_info(sbi, "Mismatch start address, segment0(%u) cp_blkaddr(%u)", +@@ -4183,12 +4183,14 @@ void f2fs_handle_critical_error(struct f2fs_sb_info *sbi, unsigned char reason, + } + + f2fs_warn(sbi, "Remounting filesystem read-only"); ++ + /* +- * Make sure updated value of ->s_mount_flags will be visible before +- * ->s_flags update ++ * We have already set CP_ERROR_FLAG flag to stop all updates ++ * to filesystem, so it doesn't need to set SB_RDONLY flag here ++ * because the flag should be set covered w/ sb->s_umount semaphore ++ * via remount procedure, otherwise, it will confuse code like ++ * freeze_super() which will lead to deadlocks and other problems. + */ +- smp_wmb(); +- sb->s_flags |= SB_RDONLY; + } + + static void f2fs_record_error_work(struct work_struct *work) +diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c +index f290fe9327c498..3f387494367963 100644 +--- a/fs/f2fs/xattr.c ++++ b/fs/f2fs/xattr.c +@@ -629,6 +629,7 @@ static int __f2fs_setxattr(struct inode *inode, int index, + const char *name, const void *value, size_t size, + struct page *ipage, int flags) + { ++ struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct f2fs_xattr_entry *here, *last; + void *base_addr, *last_base_addr; + int found, newsize; +@@ -772,9 +773,18 @@ static int __f2fs_setxattr(struct inode *inode, int index, + if (index == F2FS_XATTR_INDEX_ENCRYPTION && + !strcmp(name, F2FS_XATTR_NAME_ENCRYPTION_CONTEXT)) + f2fs_set_encrypted_inode(inode); +- if (S_ISDIR(inode->i_mode)) +- set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_CP); + ++ if (!S_ISDIR(inode->i_mode)) ++ goto same; ++ /* ++ * In restrict mode, fsync() always try to trigger checkpoint for all ++ * metadata consistency, in other mode, it triggers checkpoint when ++ * parent's xattr metadata was updated. ++ */ ++ if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_STRICT) ++ set_sbi_flag(sbi, SBI_NEED_CP); ++ else ++ f2fs_add_ino_entry(sbi, inode->i_ino, XATTR_DIR_INO); + same: + if (is_inode_flag_set(inode, FI_ACL_MODE)) { + inode->i_mode = F2FS_I(inode)->i_acl_mode; +diff --git a/fs/fcntl.c b/fs/fcntl.c +index 300e5d9ad913b5..c28dc6c005f174 100644 +--- a/fs/fcntl.c ++++ b/fs/fcntl.c +@@ -87,8 +87,8 @@ static int setfl(int fd, struct file * filp, unsigned int arg) + return error; + } + +-static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, +- int force) ++void __f_setown(struct file *filp, struct pid *pid, enum pid_type type, ++ int force) + { + write_lock_irq(&filp->f_owner.lock); + if (force || !filp->f_owner.pid) { +@@ -98,19 +98,13 @@ static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, + + if (pid) { + const struct cred *cred = current_cred(); ++ security_file_set_fowner(filp); + filp->f_owner.uid = cred->uid; + filp->f_owner.euid = cred->euid; + } + } + write_unlock_irq(&filp->f_owner.lock); + } +- +-void __f_setown(struct file *filp, struct pid *pid, enum pid_type type, +- int force) +-{ +- security_file_set_fowner(filp); +- f_modown(filp, pid, type, force); +-} + EXPORT_SYMBOL(__f_setown); + + int f_setown(struct file *filp, int who, int force) +@@ -146,7 +140,7 @@ EXPORT_SYMBOL(f_setown); + + void f_delown(struct file *filp) + { +- f_modown(filp, NULL, PIDTYPE_TGID, 1); ++ __f_setown(filp, NULL, PIDTYPE_TGID, 1); + } + + pid_t f_getown(struct file *filp) +diff --git a/fs/fs_parser.c b/fs/fs_parser.c +index a4d6ca0b8971e6..24727ec34e5aa4 100644 +--- a/fs/fs_parser.c ++++ b/fs/fs_parser.c +@@ -308,6 +308,40 @@ int fs_param_is_fd(struct p_log *log, const struct fs_parameter_spec *p, + } + EXPORT_SYMBOL(fs_param_is_fd); + ++int fs_param_is_uid(struct p_log *log, const struct fs_parameter_spec *p, ++ struct fs_parameter *param, struct fs_parse_result *result) ++{ ++ kuid_t uid; ++ ++ if (fs_param_is_u32(log, p, param, result) != 0) ++ return fs_param_bad_value(log, param); ++ ++ uid = make_kuid(current_user_ns(), result->uint_32); ++ if (!uid_valid(uid)) ++ return inval_plog(log, "Invalid uid '%s'", param->string); ++ ++ result->uid = uid; ++ return 0; ++} ++EXPORT_SYMBOL(fs_param_is_uid); ++ ++int fs_param_is_gid(struct p_log *log, const struct fs_parameter_spec *p, ++ struct fs_parameter *param, struct fs_parse_result *result) ++{ ++ kgid_t gid; ++ ++ if (fs_param_is_u32(log, p, param, result) != 0) ++ return fs_param_bad_value(log, param); ++ ++ gid = make_kgid(current_user_ns(), result->uint_32); ++ if (!gid_valid(gid)) ++ return inval_plog(log, "Invalid gid '%s'", param->string); ++ ++ result->gid = gid; ++ return 0; ++} ++EXPORT_SYMBOL(fs_param_is_gid); ++ + int fs_param_is_blockdev(struct p_log *log, const struct fs_parameter_spec *p, + struct fs_parameter *param, struct fs_parse_result *result) + { +diff --git a/fs/fuse/file.c b/fs/fuse/file.c +index ed76121f73f2e0..08f7d538ca98f4 100644 +--- a/fs/fuse/file.c ++++ b/fs/fuse/file.c +@@ -1345,7 +1345,7 @@ static bool fuse_dio_wr_exclusive_lock(struct kiocb *iocb, struct iov_iter *from + + /* shared locks are not allowed with parallel page cache IO */ + if (test_bit(FUSE_I_CACHE_IO_MODE, &fi->state)) +- return false; ++ return true; + + /* Parallel dio beyond EOF is not supported, at least for now. */ + if (fuse_io_past_eof(iocb, from)) +diff --git a/fs/inode.c b/fs/inode.c +index f5add7222c98ec..3df67672986aa9 100644 +--- a/fs/inode.c ++++ b/fs/inode.c +@@ -758,6 +758,10 @@ void evict_inodes(struct super_block *sb) + continue; + + spin_lock(&inode->i_lock); ++ if (atomic_read(&inode->i_count)) { ++ spin_unlock(&inode->i_lock); ++ continue; ++ } + if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) { + spin_unlock(&inode->i_lock); + continue; +diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c +index 5713994328cbcb..0625d1c0d0649a 100644 +--- a/fs/jfs/jfs_dmap.c ++++ b/fs/jfs/jfs_dmap.c +@@ -187,7 +187,7 @@ int dbMount(struct inode *ipbmap) + } + + bmp->db_numag = le32_to_cpu(dbmp_le->dn_numag); +- if (!bmp->db_numag) { ++ if (!bmp->db_numag || bmp->db_numag >= MAXAG) { + err = -EINVAL; + goto err_release_metapage; + } +@@ -652,7 +652,7 @@ int dbNextAG(struct inode *ipbmap) + * average free space. + */ + for (i = 0 ; i < bmp->db_numag; i++, agpref++) { +- if (agpref == bmp->db_numag) ++ if (agpref >= bmp->db_numag) + agpref = 0; + + if (atomic_read(&bmp->db_active[agpref])) +diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c +index 1407feccbc2d05..a360b24ed320c0 100644 +--- a/fs/jfs/jfs_imap.c ++++ b/fs/jfs/jfs_imap.c +@@ -1360,7 +1360,7 @@ int diAlloc(struct inode *pip, bool dir, struct inode *ip) + /* get the ag number of this iag */ + agno = BLKTOAG(JFS_IP(pip)->agstart, JFS_SBI(pip->i_sb)); + dn_numag = JFS_SBI(pip->i_sb)->bmap->db_numag; +- if (agno < 0 || agno > dn_numag) ++ if (agno < 0 || agno > dn_numag || agno >= MAXAG) + return -EIO; + + if (atomic_read(&JFS_SBI(pip->i_sb)->bmap->db_active[agno])) { +diff --git a/fs/namespace.c b/fs/namespace.c +index e1ced589d8357f..a6675c2a238394 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -2801,8 +2801,15 @@ static void mnt_warn_timestamp_expiry(struct path *mountpoint, struct vfsmount * + if (!__mnt_is_readonly(mnt) && + (!(sb->s_iflags & SB_I_TS_EXPIRY_WARNED)) && + (ktime_get_real_seconds() + TIME_UPTIME_SEC_MAX > sb->s_time_max)) { +- char *buf = (char *)__get_free_page(GFP_KERNEL); +- char *mntpath = buf ? d_path(mountpoint, buf, PAGE_SIZE) : ERR_PTR(-ENOMEM); ++ char *buf, *mntpath; ++ ++ buf = (char *)__get_free_page(GFP_KERNEL); ++ if (buf) ++ mntpath = d_path(mountpoint, buf, PAGE_SIZE); ++ else ++ mntpath = ERR_PTR(-ENOMEM); ++ if (IS_ERR(mntpath)) ++ mntpath = "(unknown)"; + + pr_warn("%s filesystem being %s at %s supports timestamps until %ptTd (0x%llx)\n", + sb->s_type->name, +@@ -2810,8 +2817,9 @@ static void mnt_warn_timestamp_expiry(struct path *mountpoint, struct vfsmount * + mntpath, &sb->s_time_max, + (unsigned long long)sb->s_time_max); + +- free_page((unsigned long)buf); + sb->s_iflags |= SB_I_TS_EXPIRY_WARNED; ++ if (buf) ++ free_page((unsigned long)buf); + } + } + +diff --git a/fs/netfs/main.c b/fs/netfs/main.c +index db824c372842ad..b1d97335d7bb83 100644 +--- a/fs/netfs/main.c ++++ b/fs/netfs/main.c +@@ -138,7 +138,7 @@ static int __init netfs_init(void) + + error_fscache: + error_procfile: +- remove_proc_entry("fs/netfs", NULL); ++ remove_proc_subtree("fs/netfs", NULL); + error_proc: + mempool_exit(&netfs_subrequest_pool); + error_subreqpool: +@@ -155,7 +155,7 @@ fs_initcall(netfs_init); + static void __exit netfs_exit(void) + { + fscache_exit(); +- remove_proc_entry("fs/netfs", NULL); ++ remove_proc_subtree("fs/netfs", NULL); + mempool_exit(&netfs_subrequest_pool); + kmem_cache_destroy(netfs_subrequest_slab); + mempool_exit(&netfs_request_pool); +diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c +index 5b452411e8fdf2..1153e166652bed 100644 +--- a/fs/nfs/nfs4state.c ++++ b/fs/nfs/nfs4state.c +@@ -1956,6 +1956,7 @@ static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recov + set_bit(ops->owner_flag_bit, &sp->so_flags); + nfs4_put_state_owner(sp); + status = nfs4_recovery_handle_error(clp, status); ++ nfs4_free_state_owners(&freeme); + return (status != 0) ? status : -EAGAIN; + } + +diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c +index f4704f5d408675..e2e248032bfd04 100644 +--- a/fs/nfsd/filecache.c ++++ b/fs/nfsd/filecache.c +@@ -1035,8 +1035,6 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp, + if (likely(ret == 0)) + goto open_file; + +- if (ret == -EEXIST) +- goto retry; + trace_nfsd_file_insert_err(rqstp, inode, may_flags, ret); + status = nfserr_jukebox; + goto construction_err; +@@ -1051,6 +1049,7 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp, + status = nfserr_jukebox; + goto construction_err; + } ++ nfsd_file_put(nf); + open_retry = false; + fh_put(fhp); + goto retry; +diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c +index 7a806ac13e317e..8cca1329f3485c 100644 +--- a/fs/nfsd/nfs4idmap.c ++++ b/fs/nfsd/nfs4idmap.c +@@ -581,6 +581,7 @@ static __be32 idmap_id_to_name(struct xdr_stream *xdr, + .id = id, + .type = type, + }; ++ __be32 status = nfs_ok; + __be32 *p; + int ret; + struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); +@@ -593,12 +594,16 @@ static __be32 idmap_id_to_name(struct xdr_stream *xdr, + return nfserrno(ret); + ret = strlen(item->name); + WARN_ON_ONCE(ret > IDMAP_NAMESZ); ++ + p = xdr_reserve_space(xdr, ret + 4); +- if (!p) +- return nfserr_resource; +- p = xdr_encode_opaque(p, item->name, ret); ++ if (unlikely(!p)) { ++ status = nfserr_resource; ++ goto out_put; ++ } ++ xdr_encode_opaque(p, item->name, ret); ++out_put: + cache_put(&item->h, nn->idtoname_cache); +- return 0; ++ return status; + } + + static bool +diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c +index 67d8673a9391c7..69a3a84e159e62 100644 +--- a/fs/nfsd/nfs4recover.c ++++ b/fs/nfsd/nfs4recover.c +@@ -809,6 +809,10 @@ __cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user *cmsg, + ci = &cmsg->cm_u.cm_clntinfo; + if (get_user(namelen, &ci->cc_name.cn_len)) + return -EFAULT; ++ if (!namelen) { ++ dprintk("%s: namelen should not be zero", __func__); ++ return -EINVAL; ++ } + name.data = memdup_user(&ci->cc_name.cn_id, namelen); + if (IS_ERR(name.data)) + return PTR_ERR(name.data); +@@ -831,6 +835,10 @@ __cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user *cmsg, + cnm = &cmsg->cm_u.cm_name; + if (get_user(namelen, &cnm->cn_len)) + return -EFAULT; ++ if (!namelen) { ++ dprintk("%s: namelen should not be zero", __func__); ++ return -EINVAL; ++ } + name.data = memdup_user(&cnm->cn_id, namelen); + if (IS_ERR(name.data)) + return PTR_ERR(name.data); +diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c +index a366fb1c1b9b4f..fe06779ea527a1 100644 +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -5912,6 +5912,28 @@ static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status) + } + } + ++static bool ++nfs4_delegation_stat(struct nfs4_delegation *dp, struct svc_fh *currentfh, ++ struct kstat *stat) ++{ ++ struct nfsd_file *nf = find_rw_file(dp->dl_stid.sc_file); ++ struct path path; ++ int rc; ++ ++ if (!nf) ++ return false; ++ ++ path.mnt = currentfh->fh_export->ex_path.mnt; ++ path.dentry = file_dentry(nf->nf_file); ++ ++ rc = vfs_getattr(&path, stat, ++ (STATX_SIZE | STATX_CTIME | STATX_CHANGE_COOKIE), ++ AT_STATX_SYNC_AS_STAT); ++ ++ nfsd_file_put(nf); ++ return rc == 0; ++} ++ + /* + * The Linux NFS server does not offer write delegations to NFSv4.0 + * clients in order to avoid conflicts between write delegations and +@@ -5947,7 +5969,6 @@ nfs4_open_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp, + int cb_up; + int status = 0; + struct kstat stat; +- struct path path; + + cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client); + open->op_recall = false; +@@ -5983,20 +6004,16 @@ nfs4_open_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp, + memcpy(&open->op_delegate_stateid, &dp->dl_stid.sc_stateid, sizeof(dp->dl_stid.sc_stateid)); + + if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) { +- open->op_delegate_type = NFS4_OPEN_DELEGATE_WRITE; +- trace_nfsd_deleg_write(&dp->dl_stid.sc_stateid); +- path.mnt = currentfh->fh_export->ex_path.mnt; +- path.dentry = currentfh->fh_dentry; +- if (vfs_getattr(&path, &stat, +- (STATX_SIZE | STATX_CTIME | STATX_CHANGE_COOKIE), +- AT_STATX_SYNC_AS_STAT)) { ++ if (!nfs4_delegation_stat(dp, currentfh, &stat)) { + nfs4_put_stid(&dp->dl_stid); + destroy_delegation(dp); + goto out_no_deleg; + } ++ open->op_delegate_type = NFS4_OPEN_DELEGATE_WRITE; + dp->dl_cb_fattr.ncf_cur_fsize = stat.size; + dp->dl_cb_fattr.ncf_initial_cinfo = + nfsd4_change_attribute(&stat, d_inode(currentfh->fh_dentry)); ++ trace_nfsd_deleg_write(&dp->dl_stid.sc_stateid); + } else { + open->op_delegate_type = NFS4_OPEN_DELEGATE_READ; + trace_nfsd_deleg_read(&dp->dl_stid.sc_stateid); +@@ -8836,6 +8853,7 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct dentry *dentry, + __be32 status; + struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); + struct file_lock_context *ctx; ++ struct nfs4_delegation *dp = NULL; + struct file_lease *fl; + struct iattr attrs; + struct nfs4_cb_fattr *ncf; +@@ -8845,84 +8863,76 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct dentry *dentry, + ctx = locks_inode_context(inode); + if (!ctx) + return 0; ++ ++#define NON_NFSD_LEASE ((void *)1) ++ + spin_lock(&ctx->flc_lock); + for_each_file_lock(fl, &ctx->flc_lease) { +- unsigned char type = fl->c.flc_type; +- + if (fl->c.flc_flags == FL_LAYOUT) + continue; +- if (fl->fl_lmops != &nfsd_lease_mng_ops) { +- /* +- * non-nfs lease, if it's a lease with F_RDLCK then +- * we are done; there isn't any write delegation +- * on this inode +- */ +- if (type == F_RDLCK) +- break; +- +- nfsd_stats_wdeleg_getattr_inc(nn); +- spin_unlock(&ctx->flc_lock); +- +- status = nfserrno(nfsd_open_break_lease(inode, NFSD_MAY_READ)); ++ if (fl->c.flc_type == F_WRLCK) { ++ if (fl->fl_lmops == &nfsd_lease_mng_ops) ++ dp = fl->c.flc_owner; ++ else ++ dp = NON_NFSD_LEASE; ++ } ++ break; ++ } ++ if (dp == NULL || dp == NON_NFSD_LEASE || ++ dp->dl_recall.cb_clp == *(rqstp->rq_lease_breaker)) { ++ spin_unlock(&ctx->flc_lock); ++ if (dp == NON_NFSD_LEASE) { ++ status = nfserrno(nfsd_open_break_lease(inode, ++ NFSD_MAY_READ)); + if (status != nfserr_jukebox || + !nfsd_wait_for_delegreturn(rqstp, inode)) + return status; +- return 0; + } +- if (type == F_WRLCK) { +- struct nfs4_delegation *dp = fl->c.flc_owner; ++ return 0; ++ } + +- if (dp->dl_recall.cb_clp == *(rqstp->rq_lease_breaker)) { +- spin_unlock(&ctx->flc_lock); +- return 0; +- } +- nfsd_stats_wdeleg_getattr_inc(nn); +- dp = fl->c.flc_owner; +- refcount_inc(&dp->dl_stid.sc_count); +- ncf = &dp->dl_cb_fattr; +- nfs4_cb_getattr(&dp->dl_cb_fattr); +- spin_unlock(&ctx->flc_lock); +- wait_on_bit_timeout(&ncf->ncf_cb_flags, CB_GETATTR_BUSY, +- TASK_INTERRUPTIBLE, NFSD_CB_GETATTR_TIMEOUT); +- if (ncf->ncf_cb_status) { +- /* Recall delegation only if client didn't respond */ +- status = nfserrno(nfsd_open_break_lease(inode, NFSD_MAY_READ)); +- if (status != nfserr_jukebox || +- !nfsd_wait_for_delegreturn(rqstp, inode)) { +- nfs4_put_stid(&dp->dl_stid); +- return status; +- } +- } +- if (!ncf->ncf_file_modified && +- (ncf->ncf_initial_cinfo != ncf->ncf_cb_change || +- ncf->ncf_cur_fsize != ncf->ncf_cb_fsize)) +- ncf->ncf_file_modified = true; +- if (ncf->ncf_file_modified) { +- int err; +- +- /* +- * Per section 10.4.3 of RFC 8881, the server would +- * not update the file's metadata with the client's +- * modified size +- */ +- attrs.ia_mtime = attrs.ia_ctime = current_time(inode); +- attrs.ia_valid = ATTR_MTIME | ATTR_CTIME | ATTR_DELEG; +- inode_lock(inode); +- err = notify_change(&nop_mnt_idmap, dentry, &attrs, NULL); +- inode_unlock(inode); +- if (err) { +- nfs4_put_stid(&dp->dl_stid); +- return nfserrno(err); +- } +- ncf->ncf_cur_fsize = ncf->ncf_cb_fsize; +- *size = ncf->ncf_cur_fsize; +- *modified = true; +- } +- nfs4_put_stid(&dp->dl_stid); +- return 0; ++ nfsd_stats_wdeleg_getattr_inc(nn); ++ refcount_inc(&dp->dl_stid.sc_count); ++ ncf = &dp->dl_cb_fattr; ++ nfs4_cb_getattr(&dp->dl_cb_fattr); ++ spin_unlock(&ctx->flc_lock); ++ ++ wait_on_bit_timeout(&ncf->ncf_cb_flags, CB_GETATTR_BUSY, ++ TASK_INTERRUPTIBLE, NFSD_CB_GETATTR_TIMEOUT); ++ if (ncf->ncf_cb_status) { ++ /* Recall delegation only if client didn't respond */ ++ status = nfserrno(nfsd_open_break_lease(inode, NFSD_MAY_READ)); ++ if (status != nfserr_jukebox || ++ !nfsd_wait_for_delegreturn(rqstp, inode)) ++ goto out_status; ++ } ++ if (!ncf->ncf_file_modified && ++ (ncf->ncf_initial_cinfo != ncf->ncf_cb_change || ++ ncf->ncf_cur_fsize != ncf->ncf_cb_fsize)) ++ ncf->ncf_file_modified = true; ++ if (ncf->ncf_file_modified) { ++ int err; ++ ++ /* ++ * Per section 10.4.3 of RFC 8881, the server would ++ * not update the file's metadata with the client's ++ * modified size ++ */ ++ attrs.ia_mtime = attrs.ia_ctime = current_time(inode); ++ attrs.ia_valid = ATTR_MTIME | ATTR_CTIME | ATTR_DELEG; ++ inode_lock(inode); ++ err = notify_change(&nop_mnt_idmap, dentry, &attrs, NULL); ++ inode_unlock(inode); ++ if (err) { ++ status = nfserrno(err); ++ goto out_status; + } +- break; ++ ncf->ncf_cur_fsize = ncf->ncf_cb_fsize; ++ *size = ncf->ncf_cur_fsize; ++ *modified = true; + } +- spin_unlock(&ctx->flc_lock); +- return 0; ++ status = 0; ++out_status: ++ nfs4_put_stid(&dp->dl_stid); ++ return status; + } +diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c +index 862bdf23120e8a..ef5061bb56da1e 100644 +--- a/fs/nilfs2/btree.c ++++ b/fs/nilfs2/btree.c +@@ -350,7 +350,7 @@ static int nilfs_btree_node_broken(const struct nilfs_btree_node *node, + if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN || + level >= NILFS_BTREE_LEVEL_MAX || + (flags & NILFS_BTREE_NODE_ROOT) || +- nchildren < 0 || ++ nchildren <= 0 || + nchildren > NILFS_BTREE_NODE_NCHILDREN_MAX(size))) { + nilfs_crit(inode->i_sb, + "bad btree node (ino=%lu, blocknr=%llu): level = %d, flags = 0x%x, nchildren = %d", +@@ -381,7 +381,8 @@ static int nilfs_btree_root_broken(const struct nilfs_btree_node *node, + if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN || + level >= NILFS_BTREE_LEVEL_MAX || + nchildren < 0 || +- nchildren > NILFS_BTREE_ROOT_NCHILDREN_MAX)) { ++ nchildren > NILFS_BTREE_ROOT_NCHILDREN_MAX || ++ (nchildren == 0 && level > NILFS_BTREE_LEVEL_NODE_MIN))) { + nilfs_crit(inode->i_sb, + "bad btree root (ino=%lu): level = %d, flags = 0x%x, nchildren = %d", + inode->i_ino, level, flags, nchildren); +@@ -1658,13 +1659,16 @@ static int nilfs_btree_check_delete(struct nilfs_bmap *btree, __u64 key) + int nchildren, ret; + + root = nilfs_btree_get_root(btree); ++ nchildren = nilfs_btree_node_get_nchildren(root); ++ if (unlikely(nchildren == 0)) ++ return 0; ++ + switch (nilfs_btree_height(btree)) { + case 2: + bh = NULL; + node = root; + break; + case 3: +- nchildren = nilfs_btree_node_get_nchildren(root); + if (nchildren > 1) + return 0; + ptr = nilfs_btree_node_get_ptr(root, nchildren - 1, +@@ -1673,12 +1677,12 @@ static int nilfs_btree_check_delete(struct nilfs_bmap *btree, __u64 key) + if (ret < 0) + return ret; + node = (struct nilfs_btree_node *)bh->b_data; ++ nchildren = nilfs_btree_node_get_nchildren(node); + break; + default: + return 0; + } + +- nchildren = nilfs_btree_node_get_nchildren(node); + maxkey = nilfs_btree_node_get_key(node, nchildren - 1); + nextmaxkey = (nchildren > 1) ? + nilfs_btree_node_get_key(node, nchildren - 2) : 0; +diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c +index 627eb2f72ef376..23fcf9e9d6c555 100644 +--- a/fs/quota/dquot.c ++++ b/fs/quota/dquot.c +@@ -2408,7 +2408,7 @@ static int vfs_setup_quota_inode(struct inode *inode, int type) + int dquot_load_quota_sb(struct super_block *sb, int type, int format_id, + unsigned int flags) + { +- struct quota_format_type *fmt = find_quota_format(format_id); ++ struct quota_format_type *fmt; + struct quota_info *dqopt = sb_dqopt(sb); + int error; + +@@ -2418,6 +2418,7 @@ int dquot_load_quota_sb(struct super_block *sb, int type, int format_id, + if (WARN_ON_ONCE(flags & DQUOT_SUSPENDED)) + return -EINVAL; + ++ fmt = find_quota_format(format_id); + if (!fmt) + return -ESRCH; + if (!sb->dq_op || !sb->s_qcop || +diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c +index 9e859ba010cf12..7cbd580120d129 100644 +--- a/fs/smb/server/vfs.c ++++ b/fs/smb/server/vfs.c +@@ -496,7 +496,7 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp, + int err = 0; + + if (work->conn->connection_type) { +- if (!(fp->daccess & FILE_WRITE_DATA_LE)) { ++ if (!(fp->daccess & (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE))) { + pr_err("no right to write(%pD)\n", fp->filp); + err = -EACCES; + goto out; +@@ -1115,9 +1115,10 @@ static bool __dir_empty(struct dir_context *ctx, const char *name, int namlen, + struct ksmbd_readdir_data *buf; + + buf = container_of(ctx, struct ksmbd_readdir_data, ctx); +- buf->dirent_count++; ++ if (!is_dot_dotdot(name, namlen)) ++ buf->dirent_count++; + +- return buf->dirent_count <= 2; ++ return !buf->dirent_count; + } + + /** +@@ -1137,7 +1138,7 @@ int ksmbd_vfs_empty_dir(struct ksmbd_file *fp) + readdir_data.dirent_count = 0; + + err = iterate_dir(fp->filp, &readdir_data.ctx); +- if (readdir_data.dirent_count > 2) ++ if (readdir_data.dirent_count) + err = -ENOTEMPTY; + else + err = 0; +@@ -1166,7 +1167,7 @@ static bool __caseless_lookup(struct dir_context *ctx, const char *name, + if (cmp < 0) + cmp = strncasecmp((char *)buf->private, name, namlen); + if (!cmp) { +- memcpy((char *)buf->private, name, namlen); ++ memcpy((char *)buf->private, name, buf->used); + buf->dirent_count = 1; + return false; + } +@@ -1234,10 +1235,7 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name, + char *filepath; + size_t path_len, remain_len; + +- filepath = kstrdup(name, GFP_KERNEL); +- if (!filepath) +- return -ENOMEM; +- ++ filepath = name; + path_len = strlen(filepath); + remain_len = path_len; + +@@ -1280,10 +1278,9 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name, + err = -EINVAL; + out2: + path_put(parent_path); +-out1: +- kfree(filepath); + } + ++out1: + if (!err) { + err = mnt_want_write(parent_path->mnt); + if (err) { +diff --git a/include/acpi/acoutput.h b/include/acpi/acoutput.h +index b1571dd96310af..5e0346142f983d 100644 +--- a/include/acpi/acoutput.h ++++ b/include/acpi/acoutput.h +@@ -193,6 +193,7 @@ + */ + #ifndef ACPI_NO_ERROR_MESSAGES + #define AE_INFO _acpi_module_name, __LINE__ ++#define ACPI_ONCE(_fn, _plist) { static char _done; if (!_done) { _done = 1; _fn _plist; } } + + /* + * Error reporting. Callers module and line number are inserted by AE_INFO, +@@ -201,8 +202,10 @@ + */ + #define ACPI_INFO(plist) acpi_info plist + #define ACPI_WARNING(plist) acpi_warning plist ++#define ACPI_WARNING_ONCE(plist) ACPI_ONCE(acpi_warning, plist) + #define ACPI_EXCEPTION(plist) acpi_exception plist + #define ACPI_ERROR(plist) acpi_error plist ++#define ACPI_ERROR_ONCE(plist) ACPI_ONCE(acpi_error, plist) + #define ACPI_BIOS_WARNING(plist) acpi_bios_warning plist + #define ACPI_BIOS_EXCEPTION(plist) acpi_bios_exception plist + #define ACPI_BIOS_ERROR(plist) acpi_bios_error plist +@@ -214,8 +217,10 @@ + + #define ACPI_INFO(plist) + #define ACPI_WARNING(plist) ++#define ACPI_WARNING_ONCE(plist) + #define ACPI_EXCEPTION(plist) + #define ACPI_ERROR(plist) ++#define ACPI_ERROR_ONCE(plist) + #define ACPI_BIOS_WARNING(plist) + #define ACPI_BIOS_EXCEPTION(plist) + #define ACPI_BIOS_ERROR(plist) +diff --git a/include/acpi/cppc_acpi.h b/include/acpi/cppc_acpi.h +index 930b6afba6f4d4..e1720d93066695 100644 +--- a/include/acpi/cppc_acpi.h ++++ b/include/acpi/cppc_acpi.h +@@ -64,6 +64,8 @@ struct cpc_desc { + int cpu_id; + int write_cmd_status; + int write_cmd_id; ++ /* Lock used for RMW operations in cpc_write() */ ++ spinlock_t rmw_lock; + struct cpc_register_resource cpc_regs[MAX_CPC_REG_ENT]; + struct acpi_psd_package domain_info; + struct kobject kobj; +diff --git a/include/linux/bpf.h b/include/linux/bpf.h +index 5e694a308081aa..5e880f0b566203 100644 +--- a/include/linux/bpf.h ++++ b/include/linux/bpf.h +@@ -694,6 +694,11 @@ enum bpf_type_flag { + /* DYNPTR points to xdp_buff */ + DYNPTR_TYPE_XDP = BIT(16 + BPF_BASE_TYPE_BITS), + ++ /* Memory must be aligned on some architectures, used in combination with ++ * MEM_FIXED_SIZE. ++ */ ++ MEM_ALIGNED = BIT(17 + BPF_BASE_TYPE_BITS), ++ + __BPF_TYPE_FLAG_MAX, + __BPF_TYPE_LAST_FLAG = __BPF_TYPE_FLAG_MAX - 1, + }; +@@ -731,8 +736,6 @@ enum bpf_arg_type { + ARG_ANYTHING, /* any (initialized) argument is ok */ + ARG_PTR_TO_SPIN_LOCK, /* pointer to bpf_spin_lock */ + ARG_PTR_TO_SOCK_COMMON, /* pointer to sock_common */ +- ARG_PTR_TO_INT, /* pointer to int */ +- ARG_PTR_TO_LONG, /* pointer to long */ + ARG_PTR_TO_SOCKET, /* pointer to bpf_sock (fullsock) */ + ARG_PTR_TO_BTF_ID, /* pointer to in-kernel struct */ + ARG_PTR_TO_RINGBUF_MEM, /* pointer to dynamically reserved ringbuf memory */ +@@ -919,6 +922,7 @@ static_assert(__BPF_REG_TYPE_MAX <= BPF_BASE_TYPE_LIMIT); + */ + struct bpf_insn_access_aux { + enum bpf_reg_type reg_type; ++ bool is_ldsx; + union { + int ctx_field_size; + struct { +@@ -927,6 +931,7 @@ struct bpf_insn_access_aux { + }; + }; + struct bpf_verifier_log *log; /* for verbose logs */ ++ bool is_retval; /* is accessing function return value ? */ + }; + + static inline void +diff --git a/include/linux/bpf_lsm.h b/include/linux/bpf_lsm.h +index 1de7ece5d36d43..aefcd656425126 100644 +--- a/include/linux/bpf_lsm.h ++++ b/include/linux/bpf_lsm.h +@@ -9,6 +9,7 @@ + + #include <linux/sched.h> + #include <linux/bpf.h> ++#include <linux/bpf_verifier.h> + #include <linux/lsm_hooks.h> + + #ifdef CONFIG_BPF_LSM +@@ -45,6 +46,8 @@ void bpf_inode_storage_free(struct inode *inode); + + void bpf_lsm_find_cgroup_shim(const struct bpf_prog *prog, bpf_func_t *bpf_func); + ++int bpf_lsm_get_retval_range(const struct bpf_prog *prog, ++ struct bpf_retval_range *range); + #else /* !CONFIG_BPF_LSM */ + + static inline bool bpf_lsm_is_sleepable_hook(u32 btf_id) +@@ -78,6 +81,11 @@ static inline void bpf_lsm_find_cgroup_shim(const struct bpf_prog *prog, + { + } + ++static inline int bpf_lsm_get_retval_range(const struct bpf_prog *prog, ++ struct bpf_retval_range *range) ++{ ++ return -EOPNOTSUPP; ++} + #endif /* CONFIG_BPF_LSM */ + + #endif /* _LINUX_BPF_LSM_H */ +diff --git a/include/linux/compiler.h b/include/linux/compiler.h +index 8c252e073bd810..7325f88736b1cd 100644 +--- a/include/linux/compiler.h ++++ b/include/linux/compiler.h +@@ -133,7 +133,7 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val, + #define annotate_unreachable() __annotate_unreachable(__COUNTER__) + + /* Annotate a C jump table to allow objtool to follow the code flow */ +-#define __annotate_jump_table __section(".rodata..c_jump_table") ++#define __annotate_jump_table __section(".rodata..c_jump_table,\"a\",@progbits #") + + #else /* !CONFIG_OBJTOOL */ + #define annotate_reachable() +diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h +index 41d1d71c36ff5d..eee8577bcc543c 100644 +--- a/include/linux/f2fs_fs.h ++++ b/include/linux/f2fs_fs.h +@@ -279,7 +279,7 @@ struct node_footer { + #define F2FS_INLINE_DATA 0x02 /* file inline data flag */ + #define F2FS_INLINE_DENTRY 0x04 /* file inline dentry flag */ + #define F2FS_DATA_EXIST 0x08 /* file inline data exist flag */ +-#define F2FS_INLINE_DOTS 0x10 /* file having implicit dot dentries */ ++#define F2FS_INLINE_DOTS 0x10 /* file having implicit dot dentries (obsolete) */ + #define F2FS_EXTRA_ATTR 0x20 /* file having extra attribute */ + #define F2FS_PIN_FILE 0x40 /* file should not be gced */ + #define F2FS_COMPRESS_RELEASED 0x80 /* file released compressed blocks */ +diff --git a/include/linux/fs_parser.h b/include/linux/fs_parser.h +index d3350979115f0a..6cf713a7e6c6fc 100644 +--- a/include/linux/fs_parser.h ++++ b/include/linux/fs_parser.h +@@ -28,7 +28,7 @@ typedef int fs_param_type(struct p_log *, + */ + fs_param_type fs_param_is_bool, fs_param_is_u32, fs_param_is_s32, fs_param_is_u64, + fs_param_is_enum, fs_param_is_string, fs_param_is_blob, fs_param_is_blockdev, +- fs_param_is_path, fs_param_is_fd; ++ fs_param_is_path, fs_param_is_fd, fs_param_is_uid, fs_param_is_gid; + + /* + * Specification of the type of value a parameter wants. +@@ -57,6 +57,8 @@ struct fs_parse_result { + int int_32; /* For spec_s32/spec_enum */ + unsigned int uint_32; /* For spec_u32{,_octal,_hex}/spec_enum */ + u64 uint_64; /* For spec_u64 */ ++ kuid_t uid; ++ kgid_t gid; + }; + }; + +@@ -131,6 +133,8 @@ static inline bool fs_validate_description(const char *name, + #define fsparam_bdev(NAME, OPT) __fsparam(fs_param_is_blockdev, NAME, OPT, 0, NULL) + #define fsparam_path(NAME, OPT) __fsparam(fs_param_is_path, NAME, OPT, 0, NULL) + #define fsparam_fd(NAME, OPT) __fsparam(fs_param_is_fd, NAME, OPT, 0, NULL) ++#define fsparam_uid(NAME, OPT) __fsparam(fs_param_is_uid, NAME, OPT, 0, NULL) ++#define fsparam_gid(NAME, OPT) __fsparam(fs_param_is_gid, NAME, OPT, 0, NULL) + + /* String parameter that allows empty argument */ + #define fsparam_string_empty(NAME, OPT) \ +diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h +index 855db460e08bc6..19c333fafe1138 100644 +--- a/include/linux/lsm_hook_defs.h ++++ b/include/linux/lsm_hook_defs.h +@@ -114,6 +114,7 @@ LSM_HOOK(int, 0, path_notify, const struct path *path, u64 mask, + unsigned int obj_type) + LSM_HOOK(int, 0, inode_alloc_security, struct inode *inode) + LSM_HOOK(void, LSM_RET_VOID, inode_free_security, struct inode *inode) ++LSM_HOOK(void, LSM_RET_VOID, inode_free_security_rcu, void *inode_security) + LSM_HOOK(int, -EOPNOTSUPP, inode_init_security, struct inode *inode, + struct inode *dir, const struct qstr *qstr, struct xattr *xattrs, + int *xattr_count) +diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h +index a2ade0ffe9e7d2..efd4a0655159cc 100644 +--- a/include/linux/lsm_hooks.h ++++ b/include/linux/lsm_hooks.h +@@ -73,6 +73,7 @@ struct lsm_blob_sizes { + int lbs_cred; + int lbs_file; + int lbs_inode; ++ int lbs_sock; + int lbs_superblock; + int lbs_ipc; + int lbs_msg_msg; +diff --git a/include/linux/sbitmap.h b/include/linux/sbitmap.h +index c09cdcc99471e1..189140bf11fc40 100644 +--- a/include/linux/sbitmap.h ++++ b/include/linux/sbitmap.h +@@ -40,7 +40,7 @@ struct sbitmap_word { + /** + * @swap_lock: serializes simultaneous updates of ->word and ->cleared + */ +- spinlock_t swap_lock; ++ raw_spinlock_t swap_lock; + } ____cacheline_aligned_in_smp; + + /** +diff --git a/include/linux/soc/qcom/geni-se.h b/include/linux/soc/qcom/geni-se.h +index 0f038a1a033099..c3bca9c0bf2cf5 100644 +--- a/include/linux/soc/qcom/geni-se.h ++++ b/include/linux/soc/qcom/geni-se.h +@@ -88,11 +88,15 @@ struct geni_se { + #define SE_GENI_M_IRQ_STATUS 0x610 + #define SE_GENI_M_IRQ_EN 0x614 + #define SE_GENI_M_IRQ_CLEAR 0x618 ++#define SE_GENI_M_IRQ_EN_SET 0x61c ++#define SE_GENI_M_IRQ_EN_CLEAR 0x620 + #define SE_GENI_S_CMD0 0x630 + #define SE_GENI_S_CMD_CTRL_REG 0x634 + #define SE_GENI_S_IRQ_STATUS 0x640 + #define SE_GENI_S_IRQ_EN 0x644 + #define SE_GENI_S_IRQ_CLEAR 0x648 ++#define SE_GENI_S_IRQ_EN_SET 0x64c ++#define SE_GENI_S_IRQ_EN_CLEAR 0x650 + #define SE_GENI_TX_FIFOn 0x700 + #define SE_GENI_RX_FIFOn 0x780 + #define SE_GENI_TX_FIFO_STATUS 0x800 +@@ -101,6 +105,8 @@ struct geni_se { + #define SE_GENI_RX_WATERMARK_REG 0x810 + #define SE_GENI_RX_RFR_WATERMARK_REG 0x814 + #define SE_GENI_IOS 0x908 ++#define SE_GENI_M_GP_LENGTH 0x910 ++#define SE_GENI_S_GP_LENGTH 0x914 + #define SE_DMA_TX_IRQ_STAT 0xc40 + #define SE_DMA_TX_IRQ_CLR 0xc44 + #define SE_DMA_TX_FSM_RST 0xc58 +@@ -234,6 +240,9 @@ struct geni_se { + #define IO2_DATA_IN BIT(1) + #define RX_DATA_IN BIT(0) + ++/* SE_GENI_M_GP_LENGTH and SE_GENI_S_GP_LENGTH fields */ ++#define GP_LENGTH GENMASK(31, 0) ++ + /* SE_DMA_TX_IRQ_STAT Register fields */ + #define TX_DMA_DONE BIT(0) + #define TX_EOT BIT(1) +diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h +index 9f08a584d70785..0b9f1e598e3a6b 100644 +--- a/include/linux/usb/usbnet.h ++++ b/include/linux/usb/usbnet.h +@@ -76,8 +76,23 @@ struct usbnet { + # define EVENT_LINK_CHANGE 11 + # define EVENT_SET_RX_MODE 12 + # define EVENT_NO_IP_ALIGN 13 ++/* This one is special, as it indicates that the device is going away ++ * there are cyclic dependencies between tasklet, timer and bh ++ * that must be broken ++ */ ++# define EVENT_UNPLUG 31 + }; + ++static inline bool usbnet_going_away(struct usbnet *ubn) ++{ ++ return test_bit(EVENT_UNPLUG, &ubn->flags); ++} ++ ++static inline void usbnet_mark_going_away(struct usbnet *ubn) ++{ ++ set_bit(EVENT_UNPLUG, &ubn->flags); ++} ++ + static inline struct usb_driver *driver_of(struct usb_interface *intf) + { + return to_usb_driver(intf->dev.driver); +diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h +index ecb6824e9add83..9cfd1ce0fd36c4 100644 +--- a/include/net/bluetooth/hci_core.h ++++ b/include/net/bluetooth/hci_core.h +@@ -2258,8 +2258,8 @@ void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, + bool mgmt_connected); + void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, + u8 link_type, u8 addr_type, u8 status); +-void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, +- u8 addr_type, u8 status); ++void mgmt_connect_failed(struct hci_dev *hdev, struct hci_conn *conn, ++ u8 status); + void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure); + void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, + u8 status); +diff --git a/include/net/ip.h b/include/net/ip.h +index c5606cadb1a552..82248813619e3f 100644 +--- a/include/net/ip.h ++++ b/include/net/ip.h +@@ -795,6 +795,8 @@ static inline void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb) + } + + bool icmp_global_allow(void); ++void icmp_global_consume(void); ++ + extern int sysctl_icmp_msgs_per_sec; + extern int sysctl_icmp_msgs_burst; + +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index 45ad37adbe3287..7b3f56d862de40 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -953,8 +953,9 @@ enum mac80211_tx_info_flags { + * of their QoS TID or other priority field values. + * @IEEE80211_TX_CTRL_MCAST_MLO_FIRST_TX: first MLO TX, used mostly internally + * for sequence number assignment +- * @IEEE80211_TX_CTRL_SCAN_TX: Indicates that this frame is transmitted +- * due to scanning, not in normal operation on the interface. ++ * @IEEE80211_TX_CTRL_DONT_USE_RATE_MASK: Don't use rate mask for this frame ++ * which is transmitted due to scanning or offchannel TX, not in normal ++ * operation on the interface. + * @IEEE80211_TX_CTRL_MLO_LINK: If not @IEEE80211_LINK_UNSPECIFIED, this + * frame should be transmitted on the specific link. This really is + * only relevant for frames that do not have data present, and is +@@ -975,7 +976,7 @@ enum mac80211_tx_control_flags { + IEEE80211_TX_CTRL_NO_SEQNO = BIT(7), + IEEE80211_TX_CTRL_DONT_REORDER = BIT(8), + IEEE80211_TX_CTRL_MCAST_MLO_FIRST_TX = BIT(9), +- IEEE80211_TX_CTRL_SCAN_TX = BIT(10), ++ IEEE80211_TX_CTRL_DONT_USE_RATE_MASK = BIT(10), + IEEE80211_TX_CTRL_MLO_LINK = 0xf0000000, + }; + +diff --git a/include/net/tcp.h b/include/net/tcp.h +index 45bbb54e42e85e..ac647c952cf0c5 100644 +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -2437,9 +2437,26 @@ static inline s64 tcp_rto_delta_us(const struct sock *sk) + { + const struct sk_buff *skb = tcp_rtx_queue_head(sk); + u32 rto = inet_csk(sk)->icsk_rto; +- u64 rto_time_stamp_us = tcp_skb_timestamp_us(skb) + jiffies_to_usecs(rto); + +- return rto_time_stamp_us - tcp_sk(sk)->tcp_mstamp; ++ if (likely(skb)) { ++ u64 rto_time_stamp_us = tcp_skb_timestamp_us(skb) + jiffies_to_usecs(rto); ++ ++ return rto_time_stamp_us - tcp_sk(sk)->tcp_mstamp; ++ } else { ++ WARN_ONCE(1, ++ "rtx queue emtpy: " ++ "out:%u sacked:%u lost:%u retrans:%u " ++ "tlp_high_seq:%u sk_state:%u ca_state:%u " ++ "advmss:%u mss_cache:%u pmtu:%u\n", ++ tcp_sk(sk)->packets_out, tcp_sk(sk)->sacked_out, ++ tcp_sk(sk)->lost_out, tcp_sk(sk)->retrans_out, ++ tcp_sk(sk)->tlp_high_seq, sk->sk_state, ++ inet_csk(sk)->icsk_ca_state, ++ tcp_sk(sk)->advmss, tcp_sk(sk)->mss_cache, ++ inet_csk(sk)->icsk_pmtu_cookie); ++ return jiffies_to_usecs(rto); ++ } ++ + } + + /* +diff --git a/include/sound/tas2781.h b/include/sound/tas2781.h +index 99ca3e401fd1fe..6f6e3e2f652c96 100644 +--- a/include/sound/tas2781.h ++++ b/include/sound/tas2781.h +@@ -80,11 +80,6 @@ struct tasdevice { + bool is_loaderr; + }; + +-struct tasdevice_irqinfo { +- int irq_gpio; +- int irq; +-}; +- + struct calidata { + unsigned char *data; + unsigned long total_sz; +@@ -92,7 +87,6 @@ struct calidata { + + struct tasdevice_priv { + struct tasdevice tasdevice[TASDEVICE_MAX_CHANNELS]; +- struct tasdevice_irqinfo irq_info; + struct tasdevice_rca rcabin; + struct calidata cali_data; + struct tasdevice_fw *fmw; +@@ -113,6 +107,7 @@ struct tasdevice_priv { + unsigned int chip_id; + unsigned int sysclk; + ++ int irq; + int cur_prog; + int cur_conf; + int fw_state; +diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h +index ed794b5fefbe3a..2851c823095bc1 100644 +--- a/include/trace/events/f2fs.h ++++ b/include/trace/events/f2fs.h +@@ -139,7 +139,8 @@ TRACE_DEFINE_ENUM(EX_BLOCK_AGE); + { CP_NODE_NEED_CP, "node needs cp" }, \ + { CP_FASTBOOT_MODE, "fastboot mode" }, \ + { CP_SPEC_LOG_NUM, "log type is 2" }, \ +- { CP_RECOVER_DIR, "dir needs recovery" }) ++ { CP_RECOVER_DIR, "dir needs recovery" }, \ ++ { CP_XATTR_DIR, "dir's xattr updated" }) + + #define show_shutdown_mode(type) \ + __print_symbolic(type, \ +diff --git a/io_uring/io-wq.c b/io_uring/io-wq.c +index 22dac5850327fc..b59a1bf844cf9d 100644 +--- a/io_uring/io-wq.c ++++ b/io_uring/io-wq.c +@@ -13,6 +13,7 @@ + #include <linux/slab.h> + #include <linux/rculist_nulls.h> + #include <linux/cpu.h> ++#include <linux/cpuset.h> + #include <linux/task_work.h> + #include <linux/audit.h> + #include <linux/mmu_context.h> +@@ -1166,7 +1167,7 @@ struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data) + + if (!alloc_cpumask_var(&wq->cpu_mask, GFP_KERNEL)) + goto err; +- cpumask_copy(wq->cpu_mask, cpu_possible_mask); ++ cpuset_cpus_allowed(data->task, wq->cpu_mask); + wq->acct[IO_WQ_ACCT_BOUND].max_workers = bounded; + wq->acct[IO_WQ_ACCT_UNBOUND].max_workers = + task_rlimit(current, RLIMIT_NPROC); +@@ -1321,17 +1322,29 @@ static int io_wq_cpu_offline(unsigned int cpu, struct hlist_node *node) + + int io_wq_cpu_affinity(struct io_uring_task *tctx, cpumask_var_t mask) + { ++ cpumask_var_t allowed_mask; ++ int ret = 0; ++ + if (!tctx || !tctx->io_wq) + return -EINVAL; + ++ if (!alloc_cpumask_var(&allowed_mask, GFP_KERNEL)) ++ return -ENOMEM; ++ + rcu_read_lock(); +- if (mask) +- cpumask_copy(tctx->io_wq->cpu_mask, mask); +- else +- cpumask_copy(tctx->io_wq->cpu_mask, cpu_possible_mask); ++ cpuset_cpus_allowed(tctx->io_wq->task, allowed_mask); ++ if (mask) { ++ if (cpumask_subset(mask, allowed_mask)) ++ cpumask_copy(tctx->io_wq->cpu_mask, mask); ++ else ++ ret = -EINVAL; ++ } else { ++ cpumask_copy(tctx->io_wq->cpu_mask, allowed_mask); ++ } + rcu_read_unlock(); + +- return 0; ++ free_cpumask_var(allowed_mask); ++ return ret; + } + + /* +diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c +index 896e707e06187f..c0d8ee0c9786df 100644 +--- a/io_uring/io_uring.c ++++ b/io_uring/io_uring.c +@@ -2401,7 +2401,7 @@ static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx, + return 1; + if (unlikely(!llist_empty(&ctx->work_llist))) + return 1; +- if (unlikely(test_thread_flag(TIF_NOTIFY_SIGNAL))) ++ if (unlikely(task_work_pending(current))) + return 1; + if (unlikely(task_sigpending(current))) + return -EINTR; +@@ -2502,9 +2502,9 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, + * If we got woken because of task_work being processed, run it + * now rather than let the caller do another wait loop. + */ +- io_run_task_work(); + if (!llist_empty(&ctx->work_llist)) + io_run_local_work(ctx, nr_wait); ++ io_run_task_work(); + + /* + * Non-local task_work will be run on exit to userspace, but +diff --git a/io_uring/rw.c b/io_uring/rw.c +index 1a2128459cb4c8..e6b44367df67b0 100644 +--- a/io_uring/rw.c ++++ b/io_uring/rw.c +@@ -856,6 +856,14 @@ static int __io_read(struct io_kiocb *req, unsigned int issue_flags) + + ret = io_iter_do_read(rw, &io->iter); + ++ /* ++ * Some file systems like to return -EOPNOTSUPP for an IOCB_NOWAIT ++ * issue, even though they should be returning -EAGAIN. To be safe, ++ * retry from blocking context for either. ++ */ ++ if (ret == -EOPNOTSUPP && force_nonblock) ++ ret = -EAGAIN; ++ + if (ret == -EAGAIN || (req->flags & REQ_F_REISSUE)) { + req->flags &= ~REQ_F_REISSUE; + /* If we can poll, just do that. */ +diff --git a/io_uring/sqpoll.c b/io_uring/sqpoll.c +index b3722e5275e77e..4dcb1c586536d7 100644 +--- a/io_uring/sqpoll.c ++++ b/io_uring/sqpoll.c +@@ -10,6 +10,7 @@ + #include <linux/slab.h> + #include <linux/audit.h> + #include <linux/security.h> ++#include <linux/cpuset.h> + #include <linux/io_uring.h> + + #include <uapi/linux/io_uring.h> +@@ -460,11 +461,22 @@ __cold int io_sq_offload_create(struct io_ring_ctx *ctx, + return 0; + + if (p->flags & IORING_SETUP_SQ_AFF) { ++ cpumask_var_t allowed_mask; + int cpu = p->sq_thread_cpu; + + ret = -EINVAL; + if (cpu >= nr_cpu_ids || !cpu_online(cpu)) + goto err_sqpoll; ++ ret = -ENOMEM; ++ if (!alloc_cpumask_var(&allowed_mask, GFP_KERNEL)) ++ goto err_sqpoll; ++ ret = -EINVAL; ++ cpuset_cpus_allowed(current, allowed_mask); ++ if (!cpumask_test_cpu(cpu, allowed_mask)) { ++ free_cpumask_var(allowed_mask); ++ goto err_sqpoll; ++ } ++ free_cpumask_var(allowed_mask); + sqd->sq_cpu = cpu; + } else { + sqd->sq_cpu = -1; +diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c +index 68240c3c6e7dea..7f8a66a62661b9 100644 +--- a/kernel/bpf/bpf_lsm.c ++++ b/kernel/bpf/bpf_lsm.c +@@ -11,7 +11,6 @@ + #include <linux/lsm_hooks.h> + #include <linux/bpf_lsm.h> + #include <linux/kallsyms.h> +-#include <linux/bpf_verifier.h> + #include <net/bpf_sk_storage.h> + #include <linux/bpf_local_storage.h> + #include <linux/btf_ids.h> +@@ -389,3 +388,36 @@ const struct bpf_verifier_ops lsm_verifier_ops = { + .get_func_proto = bpf_lsm_func_proto, + .is_valid_access = btf_ctx_access, + }; ++ ++/* hooks return 0 or 1 */ ++BTF_SET_START(bool_lsm_hooks) ++#ifdef CONFIG_SECURITY_NETWORK_XFRM ++BTF_ID(func, bpf_lsm_xfrm_state_pol_flow_match) ++#endif ++#ifdef CONFIG_AUDIT ++BTF_ID(func, bpf_lsm_audit_rule_known) ++#endif ++BTF_ID(func, bpf_lsm_inode_xattr_skipcap) ++BTF_SET_END(bool_lsm_hooks) ++ ++int bpf_lsm_get_retval_range(const struct bpf_prog *prog, ++ struct bpf_retval_range *retval_range) ++{ ++ /* no return value range for void hooks */ ++ if (!prog->aux->attach_func_proto->type) ++ return -EINVAL; ++ ++ if (btf_id_set_contains(&bool_lsm_hooks, prog->aux->attach_btf_id)) { ++ retval_range->minval = 0; ++ retval_range->maxval = 1; ++ } else { ++ /* All other available LSM hooks, except task_prctl, return 0 ++ * on success and negative error code on failure. ++ * To keep things simple, we only allow bpf progs to return 0 ++ * or negative errno for task_prctl too. ++ */ ++ retval_range->minval = -MAX_ERRNO; ++ retval_range->maxval = 0; ++ } ++ return 0; ++} +diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c +index 2f157ffbc67cea..96e8596a76ceab 100644 +--- a/kernel/bpf/btf.c ++++ b/kernel/bpf/btf.c +@@ -6250,8 +6250,11 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type, + + if (arg == nr_args) { + switch (prog->expected_attach_type) { +- case BPF_LSM_CGROUP: + case BPF_LSM_MAC: ++ /* mark we are accessing the return value */ ++ info->is_retval = true; ++ fallthrough; ++ case BPF_LSM_CGROUP: + case BPF_TRACE_FEXIT: + /* When LSM programs are attached to void LSM hooks + * they use FEXIT trampolines and when attached to +@@ -8715,6 +8718,7 @@ int bpf_core_apply(struct bpf_core_ctx *ctx, const struct bpf_core_relo *relo, + struct bpf_core_cand_list cands = {}; + struct bpf_core_relo_res targ_res; + struct bpf_core_spec *specs; ++ const struct btf_type *type; + int err; + + /* ~4k of temp memory necessary to convert LLVM spec like "0:1:0:5" +@@ -8724,6 +8728,13 @@ int bpf_core_apply(struct bpf_core_ctx *ctx, const struct bpf_core_relo *relo, + if (!specs) + return -ENOMEM; + ++ type = btf_type_by_id(ctx->btf, relo->type_id); ++ if (!type) { ++ bpf_log(ctx->log, "relo #%u: bad type id %u\n", ++ relo_idx, relo->type_id); ++ return -EINVAL; ++ } ++ + if (need_cands) { + struct bpf_cand_cache *cc; + int i; +diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c +index 7268370600f6e6..a9ae8f8e618075 100644 +--- a/kernel/bpf/helpers.c ++++ b/kernel/bpf/helpers.c +@@ -517,11 +517,12 @@ static int __bpf_strtoll(const char *buf, size_t buf_len, u64 flags, + } + + BPF_CALL_4(bpf_strtol, const char *, buf, size_t, buf_len, u64, flags, +- long *, res) ++ s64 *, res) + { + long long _res; + int err; + ++ *res = 0; + err = __bpf_strtoll(buf, buf_len, flags, &_res); + if (err < 0) + return err; +@@ -538,16 +539,18 @@ const struct bpf_func_proto bpf_strtol_proto = { + .arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY, + .arg2_type = ARG_CONST_SIZE, + .arg3_type = ARG_ANYTHING, +- .arg4_type = ARG_PTR_TO_LONG, ++ .arg4_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_ALIGNED, ++ .arg4_size = sizeof(s64), + }; + + BPF_CALL_4(bpf_strtoul, const char *, buf, size_t, buf_len, u64, flags, +- unsigned long *, res) ++ u64 *, res) + { + unsigned long long _res; + bool is_negative; + int err; + ++ *res = 0; + err = __bpf_strtoull(buf, buf_len, flags, &_res, &is_negative); + if (err < 0) + return err; +@@ -566,7 +569,8 @@ const struct bpf_func_proto bpf_strtoul_proto = { + .arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY, + .arg2_type = ARG_CONST_SIZE, + .arg3_type = ARG_ANYTHING, +- .arg4_type = ARG_PTR_TO_LONG, ++ .arg4_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_ALIGNED, ++ .arg4_size = sizeof(u64), + }; + + BPF_CALL_3(bpf_strncmp, const char *, s1, u32, s1_sz, const char *, s2) +diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c +index f45ed6adc092af..f6b6d297fad6ed 100644 +--- a/kernel/bpf/syscall.c ++++ b/kernel/bpf/syscall.c +@@ -5910,6 +5910,7 @@ static const struct bpf_func_proto bpf_sys_close_proto = { + + BPF_CALL_4(bpf_kallsyms_lookup_name, const char *, name, int, name_sz, int, flags, u64 *, res) + { ++ *res = 0; + if (flags) + return -EINVAL; + +@@ -5930,7 +5931,8 @@ static const struct bpf_func_proto bpf_kallsyms_lookup_name_proto = { + .arg1_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_CONST_SIZE_OR_ZERO, + .arg3_type = ARG_ANYTHING, +- .arg4_type = ARG_PTR_TO_LONG, ++ .arg4_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_ALIGNED, ++ .arg4_size = sizeof(u64), + }; + + static const struct bpf_func_proto * +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 73f55f4b945eed..c821713249c81d 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -2334,6 +2334,25 @@ static void mark_reg_unknown(struct bpf_verifier_env *env, + __mark_reg_unknown(env, regs + regno); + } + ++static int __mark_reg_s32_range(struct bpf_verifier_env *env, ++ struct bpf_reg_state *regs, ++ u32 regno, ++ s32 s32_min, ++ s32 s32_max) ++{ ++ struct bpf_reg_state *reg = regs + regno; ++ ++ reg->s32_min_value = max_t(s32, reg->s32_min_value, s32_min); ++ reg->s32_max_value = min_t(s32, reg->s32_max_value, s32_max); ++ ++ reg->smin_value = max_t(s64, reg->smin_value, s32_min); ++ reg->smax_value = min_t(s64, reg->smax_value, s32_max); ++ ++ reg_bounds_sync(reg); ++ ++ return reg_bounds_sanity_check(env, reg, "s32_range"); ++} ++ + static void __mark_reg_not_init(const struct bpf_verifier_env *env, + struct bpf_reg_state *reg) + { +@@ -5575,11 +5594,13 @@ static int check_packet_access(struct bpf_verifier_env *env, u32 regno, int off, + /* check access to 'struct bpf_context' fields. Supports fixed offsets only */ + static int check_ctx_access(struct bpf_verifier_env *env, int insn_idx, int off, int size, + enum bpf_access_type t, enum bpf_reg_type *reg_type, +- struct btf **btf, u32 *btf_id) ++ struct btf **btf, u32 *btf_id, bool *is_retval, bool is_ldsx) + { + struct bpf_insn_access_aux info = { + .reg_type = *reg_type, + .log = &env->log, ++ .is_retval = false, ++ .is_ldsx = is_ldsx, + }; + + if (env->ops->is_valid_access && +@@ -5592,6 +5613,7 @@ static int check_ctx_access(struct bpf_verifier_env *env, int insn_idx, int off, + * type of narrower access. + */ + *reg_type = info.reg_type; ++ *is_retval = info.is_retval; + + if (base_type(*reg_type) == PTR_TO_BTF_ID) { + *btf = info.btf; +@@ -6760,6 +6782,17 @@ static int check_stack_access_within_bounds( + return grow_stack_state(env, state, -min_off /* size */); + } + ++static bool get_func_retval_range(struct bpf_prog *prog, ++ struct bpf_retval_range *range) ++{ ++ if (prog->type == BPF_PROG_TYPE_LSM && ++ prog->expected_attach_type == BPF_LSM_MAC && ++ !bpf_lsm_get_retval_range(prog, range)) { ++ return true; ++ } ++ return false; ++} ++ + /* check whether memory at (regno + off) is accessible for t = (read | write) + * if t==write, value_regno is a register which value is stored into memory + * if t==read, value_regno is a register which will receive the value from memory +@@ -6864,6 +6897,8 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn + if (!err && value_regno >= 0 && (t == BPF_READ || rdonly_mem)) + mark_reg_unknown(env, regs, value_regno); + } else if (reg->type == PTR_TO_CTX) { ++ bool is_retval = false; ++ struct bpf_retval_range range; + enum bpf_reg_type reg_type = SCALAR_VALUE; + struct btf *btf = NULL; + u32 btf_id = 0; +@@ -6879,7 +6914,7 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn + return err; + + err = check_ctx_access(env, insn_idx, off, size, t, ®_type, &btf, +- &btf_id); ++ &btf_id, &is_retval, is_ldsx); + if (err) + verbose_linfo(env, insn_idx, "; "); + if (!err && t == BPF_READ && value_regno >= 0) { +@@ -6888,7 +6923,14 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn + * case, we know the offset is zero. + */ + if (reg_type == SCALAR_VALUE) { +- mark_reg_unknown(env, regs, value_regno); ++ if (is_retval && get_func_retval_range(env->prog, &range)) { ++ err = __mark_reg_s32_range(env, regs, value_regno, ++ range.minval, range.maxval); ++ if (err) ++ return err; ++ } else { ++ mark_reg_unknown(env, regs, value_regno); ++ } + } else { + mark_reg_known_zero(env, regs, + value_regno); +@@ -8116,6 +8158,12 @@ static bool arg_type_is_mem_size(enum bpf_arg_type type) + type == ARG_CONST_SIZE_OR_ZERO; + } + ++static bool arg_type_is_raw_mem(enum bpf_arg_type type) ++{ ++ return base_type(type) == ARG_PTR_TO_MEM && ++ type & MEM_UNINIT; ++} ++ + static bool arg_type_is_release(enum bpf_arg_type type) + { + return type & OBJ_RELEASE; +@@ -8126,16 +8174,6 @@ static bool arg_type_is_dynptr(enum bpf_arg_type type) + return base_type(type) == ARG_PTR_TO_DYNPTR; + } + +-static int int_ptr_type_to_size(enum bpf_arg_type type) +-{ +- if (type == ARG_PTR_TO_INT) +- return sizeof(u32); +- else if (type == ARG_PTR_TO_LONG) +- return sizeof(u64); +- +- return -EINVAL; +-} +- + static int resolve_map_arg_type(struct bpf_verifier_env *env, + const struct bpf_call_arg_meta *meta, + enum bpf_arg_type *arg_type) +@@ -8208,16 +8246,6 @@ static const struct bpf_reg_types mem_types = { + }, + }; + +-static const struct bpf_reg_types int_ptr_types = { +- .types = { +- PTR_TO_STACK, +- PTR_TO_PACKET, +- PTR_TO_PACKET_META, +- PTR_TO_MAP_KEY, +- PTR_TO_MAP_VALUE, +- }, +-}; +- + static const struct bpf_reg_types spin_lock_types = { + .types = { + PTR_TO_MAP_VALUE, +@@ -8273,8 +8301,6 @@ static const struct bpf_reg_types *compatible_reg_types[__BPF_ARG_TYPE_MAX] = { + [ARG_PTR_TO_SPIN_LOCK] = &spin_lock_types, + [ARG_PTR_TO_MEM] = &mem_types, + [ARG_PTR_TO_RINGBUF_MEM] = &ringbuf_mem_types, +- [ARG_PTR_TO_INT] = &int_ptr_types, +- [ARG_PTR_TO_LONG] = &int_ptr_types, + [ARG_PTR_TO_PERCPU_BTF_ID] = &percpu_btf_ptr_types, + [ARG_PTR_TO_FUNC] = &func_ptr_types, + [ARG_PTR_TO_STACK] = &stack_ptr_types, +@@ -8835,9 +8861,11 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg, + */ + meta->raw_mode = arg_type & MEM_UNINIT; + if (arg_type & MEM_FIXED_SIZE) { +- err = check_helper_mem_access(env, regno, +- fn->arg_size[arg], false, +- meta); ++ err = check_helper_mem_access(env, regno, fn->arg_size[arg], false, meta); ++ if (err) ++ return err; ++ if (arg_type & MEM_ALIGNED) ++ err = check_ptr_alignment(env, reg, 0, fn->arg_size[arg], true); + } + break; + case ARG_CONST_SIZE: +@@ -8862,17 +8890,6 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg, + if (err) + return err; + break; +- case ARG_PTR_TO_INT: +- case ARG_PTR_TO_LONG: +- { +- int size = int_ptr_type_to_size(arg_type); +- +- err = check_helper_mem_access(env, regno, size, false, meta); +- if (err) +- return err; +- err = check_ptr_alignment(env, reg, 0, size, true); +- break; +- } + case ARG_PTR_TO_CONST_STR: + { + err = check_reg_const_str(env, reg, regno); +@@ -9189,15 +9206,15 @@ static bool check_raw_mode_ok(const struct bpf_func_proto *fn) + { + int count = 0; + +- if (fn->arg1_type == ARG_PTR_TO_UNINIT_MEM) ++ if (arg_type_is_raw_mem(fn->arg1_type)) + count++; +- if (fn->arg2_type == ARG_PTR_TO_UNINIT_MEM) ++ if (arg_type_is_raw_mem(fn->arg2_type)) + count++; +- if (fn->arg3_type == ARG_PTR_TO_UNINIT_MEM) ++ if (arg_type_is_raw_mem(fn->arg3_type)) + count++; +- if (fn->arg4_type == ARG_PTR_TO_UNINIT_MEM) ++ if (arg_type_is_raw_mem(fn->arg4_type)) + count++; +- if (fn->arg5_type == ARG_PTR_TO_UNINIT_MEM) ++ if (arg_type_is_raw_mem(fn->arg5_type)) + count++; + + /* We only support one arg being in raw mode at the moment, +@@ -9911,9 +9928,13 @@ static bool in_rbtree_lock_required_cb(struct bpf_verifier_env *env) + return is_rbtree_lock_required_kfunc(kfunc_btf_id); + } + +-static bool retval_range_within(struct bpf_retval_range range, const struct bpf_reg_state *reg) ++static bool retval_range_within(struct bpf_retval_range range, const struct bpf_reg_state *reg, ++ bool return_32bit) + { +- return range.minval <= reg->smin_value && reg->smax_value <= range.maxval; ++ if (return_32bit) ++ return range.minval <= reg->s32_min_value && reg->s32_max_value <= range.maxval; ++ else ++ return range.minval <= reg->smin_value && reg->smax_value <= range.maxval; + } + + static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx) +@@ -9950,8 +9971,8 @@ static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx) + if (err) + return err; + +- /* enforce R0 return value range */ +- if (!retval_range_within(callee->callback_ret_range, r0)) { ++ /* enforce R0 return value range, and bpf_callback_t returns 64bit */ ++ if (!retval_range_within(callee->callback_ret_range, r0, false)) { + verbose_invalid_scalar(env, r0, callee->callback_ret_range, + "At callback return", "R0"); + return -EINVAL; +@@ -15572,6 +15593,7 @@ static int check_return_code(struct bpf_verifier_env *env, int regno, const char + int err; + struct bpf_func_state *frame = env->cur_state->frame[0]; + const bool is_subprog = frame->subprogno; ++ bool return_32bit = false; + + /* LSM and struct_ops func-ptr's return type could be "void" */ + if (!is_subprog || frame->in_exception_callback_fn) { +@@ -15677,12 +15699,14 @@ static int check_return_code(struct bpf_verifier_env *env, int regno, const char + + case BPF_PROG_TYPE_LSM: + if (env->prog->expected_attach_type != BPF_LSM_CGROUP) { +- /* Regular BPF_PROG_TYPE_LSM programs can return +- * any value. +- */ +- return 0; +- } +- if (!env->prog->aux->attach_func_proto->type) { ++ /* no range found, any return value is allowed */ ++ if (!get_func_retval_range(env->prog, &range)) ++ return 0; ++ /* no restricted range, any return value is allowed */ ++ if (range.minval == S32_MIN && range.maxval == S32_MAX) ++ return 0; ++ return_32bit = true; ++ } else if (!env->prog->aux->attach_func_proto->type) { + /* Make sure programs that attach to void + * hooks don't try to modify return value. + */ +@@ -15712,7 +15736,7 @@ static int check_return_code(struct bpf_verifier_env *env, int regno, const char + if (err) + return err; + +- if (!retval_range_within(range, reg)) { ++ if (!retval_range_within(range, reg, return_32bit)) { + verbose_invalid_scalar(env, reg, range, exit_ctx, reg_name); + if (!is_subprog && + prog->expected_attach_type == BPF_LSM_CGROUP && +diff --git a/kernel/kthread.c b/kernel/kthread.c +index f7be976ff88af7..db4ceb0f503cca 100644 +--- a/kernel/kthread.c ++++ b/kernel/kthread.c +@@ -845,8 +845,16 @@ int kthread_worker_fn(void *worker_ptr) + * event only cares about the address. + */ + trace_sched_kthread_work_execute_end(work, func); +- } else if (!freezing(current)) ++ } else if (!freezing(current)) { + schedule(); ++ } else { ++ /* ++ * Handle the case where the current remains ++ * TASK_INTERRUPTIBLE. try_to_freeze() expects ++ * the current to be TASK_RUNNING. ++ */ ++ __set_current_state(TASK_RUNNING); ++ } + + try_to_freeze(); + cond_resched(); +diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c +index 151bd3de59363a..3468d8230e5f75 100644 +--- a/kernel/locking/lockdep.c ++++ b/kernel/locking/lockdep.c +@@ -6184,25 +6184,27 @@ static struct pending_free *get_pending_free(void) + static void free_zapped_rcu(struct rcu_head *cb); + + /* +- * Schedule an RCU callback if no RCU callback is pending. Must be called with +- * the graph lock held. +- */ +-static void call_rcu_zapped(struct pending_free *pf) ++* See if we need to queue an RCU callback, must called with ++* the lockdep lock held, returns false if either we don't have ++* any pending free or the callback is already scheduled. ++* Otherwise, a call_rcu() must follow this function call. ++*/ ++static bool prepare_call_rcu_zapped(struct pending_free *pf) + { + WARN_ON_ONCE(inside_selftest()); + + if (list_empty(&pf->zapped)) +- return; ++ return false; + + if (delayed_free.scheduled) +- return; ++ return false; + + delayed_free.scheduled = true; + + WARN_ON_ONCE(delayed_free.pf + delayed_free.index != pf); + delayed_free.index ^= 1; + +- call_rcu(&delayed_free.rcu_head, free_zapped_rcu); ++ return true; + } + + /* The caller must hold the graph lock. May be called from RCU context. */ +@@ -6228,6 +6230,7 @@ static void free_zapped_rcu(struct rcu_head *ch) + { + struct pending_free *pf; + unsigned long flags; ++ bool need_callback; + + if (WARN_ON_ONCE(ch != &delayed_free.rcu_head)) + return; +@@ -6239,14 +6242,18 @@ static void free_zapped_rcu(struct rcu_head *ch) + pf = delayed_free.pf + (delayed_free.index ^ 1); + __free_zapped_classes(pf); + delayed_free.scheduled = false; ++ need_callback = ++ prepare_call_rcu_zapped(delayed_free.pf + delayed_free.index); ++ lockdep_unlock(); ++ raw_local_irq_restore(flags); + + /* +- * If there's anything on the open list, close and start a new callback. +- */ +- call_rcu_zapped(delayed_free.pf + delayed_free.index); ++ * If there's pending free and its callback has not been scheduled, ++ * queue an RCU callback. ++ */ ++ if (need_callback) ++ call_rcu(&delayed_free.rcu_head, free_zapped_rcu); + +- lockdep_unlock(); +- raw_local_irq_restore(flags); + } + + /* +@@ -6286,6 +6293,7 @@ static void lockdep_free_key_range_reg(void *start, unsigned long size) + { + struct pending_free *pf; + unsigned long flags; ++ bool need_callback; + + init_data_structures_once(); + +@@ -6293,10 +6301,11 @@ static void lockdep_free_key_range_reg(void *start, unsigned long size) + lockdep_lock(); + pf = get_pending_free(); + __lockdep_free_key_range(pf, start, size); +- call_rcu_zapped(pf); ++ need_callback = prepare_call_rcu_zapped(pf); + lockdep_unlock(); + raw_local_irq_restore(flags); +- ++ if (need_callback) ++ call_rcu(&delayed_free.rcu_head, free_zapped_rcu); + /* + * Wait for any possible iterators from look_up_lock_class() to pass + * before continuing to free the memory they refer to. +@@ -6390,6 +6399,7 @@ static void lockdep_reset_lock_reg(struct lockdep_map *lock) + struct pending_free *pf; + unsigned long flags; + int locked; ++ bool need_callback = false; + + raw_local_irq_save(flags); + locked = graph_lock(); +@@ -6398,11 +6408,13 @@ static void lockdep_reset_lock_reg(struct lockdep_map *lock) + + pf = get_pending_free(); + __lockdep_reset_lock(pf, lock); +- call_rcu_zapped(pf); ++ need_callback = prepare_call_rcu_zapped(pf); + + graph_unlock(); + out_irq: + raw_local_irq_restore(flags); ++ if (need_callback) ++ call_rcu(&delayed_free.rcu_head, free_zapped_rcu); + } + + /* +@@ -6446,6 +6458,7 @@ void lockdep_unregister_key(struct lock_class_key *key) + struct pending_free *pf; + unsigned long flags; + bool found = false; ++ bool need_callback = false; + + might_sleep(); + +@@ -6466,11 +6479,14 @@ void lockdep_unregister_key(struct lock_class_key *key) + if (found) { + pf = get_pending_free(); + __lockdep_free_key_range(pf, key, 1); +- call_rcu_zapped(pf); ++ need_callback = prepare_call_rcu_zapped(pf); + } + lockdep_unlock(); + raw_local_irq_restore(flags); + ++ if (need_callback) ++ call_rcu(&delayed_free.rcu_head, free_zapped_rcu); ++ + /* Wait until is_dynamic_key() has finished accessing k->hash_entry. */ + synchronize_rcu(); + } +diff --git a/kernel/module/Makefile b/kernel/module/Makefile +index a10b2b9a6fdfc6..50ffcc413b5450 100644 +--- a/kernel/module/Makefile ++++ b/kernel/module/Makefile +@@ -5,7 +5,7 @@ + + # These are called from save_stack_trace() on slub debug path, + # and produce insane amounts of uninteresting coverage. +-KCOV_INSTRUMENT_module.o := n ++KCOV_INSTRUMENT_main.o := n + + obj-y += main.o + obj-y += strict_rwx.o +diff --git a/kernel/padata.c b/kernel/padata.c +index 0fa6c289546032..d899f34558afcc 100644 +--- a/kernel/padata.c ++++ b/kernel/padata.c +@@ -404,7 +404,8 @@ void padata_do_serial(struct padata_priv *padata) + /* Sort in ascending order of sequence number. */ + list_for_each_prev(pos, &reorder->list) { + cur = list_entry(pos, struct padata_priv, list); +- if (cur->seq_nr < padata->seq_nr) ++ /* Compare by difference to consider integer wrap around */ ++ if ((signed int)(cur->seq_nr - padata->seq_nr) < 0) + break; + } + list_add(&padata->list, pos); +@@ -512,9 +513,12 @@ void __init padata_do_multithreaded(struct padata_mt_job *job) + * thread function. Load balance large jobs between threads by + * increasing the number of chunks, guarantee at least the minimum + * chunk size from the caller, and honor the caller's alignment. ++ * Ensure chunk_size is at least 1 to prevent divide-by-0 ++ * panic in padata_mt_helper(). + */ + ps.chunk_size = job->size / (ps.nworks * load_balance_factor); + ps.chunk_size = max(ps.chunk_size, job->min_chunk); ++ ps.chunk_size = max(ps.chunk_size, 1ul); + ps.chunk_size = roundup(ps.chunk_size, job->align); + + /* +diff --git a/kernel/rcu/tree_nocb.h b/kernel/rcu/tree_nocb.h +index 2d9eed2bf75093..9b485f1060c017 100644 +--- a/kernel/rcu/tree_nocb.h ++++ b/kernel/rcu/tree_nocb.h +@@ -220,7 +220,10 @@ static bool __wake_nocb_gp(struct rcu_data *rdp_gp, + raw_spin_unlock_irqrestore(&rdp_gp->nocb_gp_lock, flags); + if (needwake) { + trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("DoWake")); +- wake_up_process(rdp_gp->nocb_gp_kthread); ++ if (cpu_is_offline(raw_smp_processor_id())) ++ swake_up_one_online(&rdp_gp->nocb_gp_wq); ++ else ++ wake_up_process(rdp_gp->nocb_gp_kthread); + } + + return needwake; +diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c +index 9bedd148f0075c..09faca47e90fb8 100644 +--- a/kernel/sched/deadline.c ++++ b/kernel/sched/deadline.c +@@ -1599,46 +1599,40 @@ static inline bool __dl_less(struct rb_node *a, const struct rb_node *b) + return dl_time_before(__node_2_dle(a)->deadline, __node_2_dle(b)->deadline); + } + +-static inline struct sched_statistics * ++static __always_inline struct sched_statistics * + __schedstats_from_dl_se(struct sched_dl_entity *dl_se) + { ++ if (!schedstat_enabled()) ++ return NULL; ++ ++ if (dl_server(dl_se)) ++ return NULL; ++ + return &dl_task_of(dl_se)->stats; + } + + static inline void + update_stats_wait_start_dl(struct dl_rq *dl_rq, struct sched_dl_entity *dl_se) + { +- struct sched_statistics *stats; +- +- if (!schedstat_enabled()) +- return; +- +- stats = __schedstats_from_dl_se(dl_se); +- __update_stats_wait_start(rq_of_dl_rq(dl_rq), dl_task_of(dl_se), stats); ++ struct sched_statistics *stats = __schedstats_from_dl_se(dl_se); ++ if (stats) ++ __update_stats_wait_start(rq_of_dl_rq(dl_rq), dl_task_of(dl_se), stats); + } + + static inline void + update_stats_wait_end_dl(struct dl_rq *dl_rq, struct sched_dl_entity *dl_se) + { +- struct sched_statistics *stats; +- +- if (!schedstat_enabled()) +- return; +- +- stats = __schedstats_from_dl_se(dl_se); +- __update_stats_wait_end(rq_of_dl_rq(dl_rq), dl_task_of(dl_se), stats); ++ struct sched_statistics *stats = __schedstats_from_dl_se(dl_se); ++ if (stats) ++ __update_stats_wait_end(rq_of_dl_rq(dl_rq), dl_task_of(dl_se), stats); + } + + static inline void + update_stats_enqueue_sleeper_dl(struct dl_rq *dl_rq, struct sched_dl_entity *dl_se) + { +- struct sched_statistics *stats; +- +- if (!schedstat_enabled()) +- return; +- +- stats = __schedstats_from_dl_se(dl_se); +- __update_stats_enqueue_sleeper(rq_of_dl_rq(dl_rq), dl_task_of(dl_se), stats); ++ struct sched_statistics *stats = __schedstats_from_dl_se(dl_se); ++ if (stats) ++ __update_stats_enqueue_sleeper(rq_of_dl_rq(dl_rq), dl_task_of(dl_se), stats); + } + + static inline void +diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c +index 483c137b9d3d7e..5e4162d02afc15 100644 +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -511,7 +511,7 @@ static int cfs_rq_is_idle(struct cfs_rq *cfs_rq) + + static int se_is_idle(struct sched_entity *se) + { +- return 0; ++ return task_has_idle_policy(task_of(se)); + } + + #endif /* CONFIG_FAIR_GROUP_SCHED */ +@@ -3188,6 +3188,15 @@ static bool vma_is_accessed(struct mm_struct *mm, struct vm_area_struct *vma) + return true; + } + ++ /* ++ * This vma has not been accessed for a while, and if the number ++ * the threads in the same process is low, which means no other ++ * threads can help scan this vma, force a vma scan. ++ */ ++ if (READ_ONCE(mm->numa_scan_seq) > ++ (vma->numab_state->prev_scan_seq + get_nr_threads(current))) ++ return true; ++ + return false; + } + +@@ -8381,16 +8390,7 @@ static void check_preempt_wakeup_fair(struct rq *rq, struct task_struct *p, int + if (test_tsk_need_resched(curr)) + return; + +- /* Idle tasks are by definition preempted by non-idle tasks. */ +- if (unlikely(task_has_idle_policy(curr)) && +- likely(!task_has_idle_policy(p))) +- goto preempt; +- +- /* +- * Batch and idle tasks do not preempt non-idle tasks (their preemption +- * is driven by the tick): +- */ +- if (unlikely(p->policy != SCHED_NORMAL) || !sched_feat(WAKEUP_PREEMPTION)) ++ if (!sched_feat(WAKEUP_PREEMPTION)) + return; + + find_matching_se(&se, &pse); +@@ -8400,7 +8400,7 @@ static void check_preempt_wakeup_fair(struct rq *rq, struct task_struct *p, int + pse_is_idle = se_is_idle(pse); + + /* +- * Preempt an idle group in favor of a non-idle group (and don't preempt ++ * Preempt an idle entity in favor of a non-idle entity (and don't preempt + * in the inverse case). + */ + if (cse_is_idle && !pse_is_idle) +@@ -8408,9 +8408,14 @@ static void check_preempt_wakeup_fair(struct rq *rq, struct task_struct *p, int + if (cse_is_idle != pse_is_idle) + return; + ++ /* ++ * BATCH and IDLE tasks do not preempt others. ++ */ ++ if (unlikely(p->policy != SCHED_NORMAL)) ++ return; ++ + cfs_rq = cfs_rq_of(se); + update_curr(cfs_rq); +- + /* + * XXX pick_eevdf(cfs_rq) != se ? + */ +@@ -9360,9 +9365,10 @@ static bool __update_blocked_others(struct rq *rq, bool *done) + + hw_pressure = arch_scale_hw_pressure(cpu_of(rq)); + ++ /* hw_pressure doesn't care about invariance */ + decayed = update_rt_rq_load_avg(now, rq, curr_class == &rt_sched_class) | + update_dl_rq_load_avg(now, rq, curr_class == &dl_sched_class) | +- update_hw_load_avg(now, rq, hw_pressure) | ++ update_hw_load_avg(rq_clock_task(rq), rq, hw_pressure) | + update_irq_load_avg(rq, 0); + + if (others_have_blocked(rq)) +diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c +index d1daeab1bbc141..433be6bc8b7786 100644 +--- a/kernel/trace/bpf_trace.c ++++ b/kernel/trace/bpf_trace.c +@@ -1226,7 +1226,8 @@ static const struct bpf_func_proto bpf_get_func_arg_proto = { + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, +- .arg3_type = ARG_PTR_TO_LONG, ++ .arg3_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_ALIGNED, ++ .arg3_size = sizeof(u64), + }; + + BPF_CALL_2(get_func_ret, void *, ctx, u64 *, value) +@@ -1242,7 +1243,8 @@ static const struct bpf_func_proto bpf_get_func_ret_proto = { + .func = get_func_ret, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, +- .arg2_type = ARG_PTR_TO_LONG, ++ .arg2_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_ALIGNED, ++ .arg2_size = sizeof(u64), + }; + + BPF_CALL_1(get_func_arg_cnt, void *, ctx) +@@ -3482,17 +3484,20 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr + uprobes[i].ref_ctr_offset, + &uprobes[i].consumer); + if (err) { +- bpf_uprobe_unregister(&path, uprobes, i); +- goto error_free; ++ link->cnt = i; ++ goto error_unregister; + } + } + + err = bpf_link_prime(&link->link, &link_primer); + if (err) +- goto error_free; ++ goto error_unregister; + + return bpf_link_settle(&link_primer); + ++error_unregister: ++ bpf_uprobe_unregister(&path, uprobes, link->cnt); ++ + error_free: + kvfree(uprobes); + kfree(link); +diff --git a/lib/debugobjects.c b/lib/debugobjects.c +index 7cea91e193a8f0..1ea8af72849cdb 100644 +--- a/lib/debugobjects.c ++++ b/lib/debugobjects.c +@@ -142,13 +142,14 @@ static void fill_pool(void) + * READ_ONCE()s pair with the WRITE_ONCE()s in pool_lock critical + * sections. + */ +- while (READ_ONCE(obj_nr_tofree) && (READ_ONCE(obj_pool_free) < obj_pool_min_free)) { ++ while (READ_ONCE(obj_nr_tofree) && ++ READ_ONCE(obj_pool_free) < debug_objects_pool_min_level) { + raw_spin_lock_irqsave(&pool_lock, flags); + /* + * Recheck with the lock held as the worker thread might have + * won the race and freed the global free list already. + */ +- while (obj_nr_tofree && (obj_pool_free < obj_pool_min_free)) { ++ while (obj_nr_tofree && (obj_pool_free < debug_objects_pool_min_level)) { + obj = hlist_entry(obj_to_free.first, typeof(*obj), node); + hlist_del(&obj->node); + WRITE_ONCE(obj_nr_tofree, obj_nr_tofree - 1); +diff --git a/lib/sbitmap.c b/lib/sbitmap.c +index 5e2e93307f0d05..d3412984170c03 100644 +--- a/lib/sbitmap.c ++++ b/lib/sbitmap.c +@@ -65,7 +65,7 @@ static inline bool sbitmap_deferred_clear(struct sbitmap_word *map, + { + unsigned long mask, word_mask; + +- guard(spinlock_irqsave)(&map->swap_lock); ++ guard(raw_spinlock_irqsave)(&map->swap_lock); + + if (!map->cleared) { + if (depth == 0) +@@ -136,7 +136,7 @@ int sbitmap_init_node(struct sbitmap *sb, unsigned int depth, int shift, + } + + for (i = 0; i < sb->map_nr; i++) +- spin_lock_init(&sb->map[i].swap_lock); ++ raw_spin_lock_init(&sb->map[i].swap_lock); + + return 0; + } +diff --git a/lib/xz/xz_crc32.c b/lib/xz/xz_crc32.c +index 88a2c35e1b5971..5627b00fca296e 100644 +--- a/lib/xz/xz_crc32.c ++++ b/lib/xz/xz_crc32.c +@@ -29,7 +29,7 @@ STATIC_RW_DATA uint32_t xz_crc32_table[256]; + + XZ_EXTERN void xz_crc32_init(void) + { +- const uint32_t poly = CRC32_POLY_LE; ++ const uint32_t poly = 0xEDB88320; + + uint32_t i; + uint32_t j; +diff --git a/lib/xz/xz_private.h b/lib/xz/xz_private.h +index bf1e94ec7873cf..d9fd49b45fd758 100644 +--- a/lib/xz/xz_private.h ++++ b/lib/xz/xz_private.h +@@ -105,10 +105,6 @@ + # endif + #endif + +-#ifndef CRC32_POLY_LE +-#define CRC32_POLY_LE 0xedb88320 +-#endif +- + /* + * Allocate memory for LZMA2 decoder. xz_dec_lzma2_reset() must be used + * before calling xz_dec_lzma2_run(). +diff --git a/mm/damon/vaddr.c b/mm/damon/vaddr.c +index 381559e4a1faba..26877b290de63a 100644 +--- a/mm/damon/vaddr.c ++++ b/mm/damon/vaddr.c +@@ -126,6 +126,7 @@ static int __damon_va_three_regions(struct mm_struct *mm, + * If this is too slow, it can be optimised to examine the maple + * tree gaps. + */ ++ rcu_read_lock(); + for_each_vma(vmi, vma) { + unsigned long gap; + +@@ -146,6 +147,7 @@ static int __damon_va_three_regions(struct mm_struct *mm, + next: + prev = vma; + } ++ rcu_read_unlock(); + + if (!sz_range(&second_gap) || !sz_range(&first_gap)) + return -EINVAL; +diff --git a/mm/huge_memory.c b/mm/huge_memory.c +index 4d9c1277e5e4d1..cedc93028894c6 100644 +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -214,6 +214,8 @@ static bool get_huge_zero_page(void) + count_vm_event(THP_ZERO_PAGE_ALLOC_FAILED); + return false; + } ++ /* Ensure zero folio won't have large_rmappable flag set. */ ++ folio_clear_large_rmappable(zero_folio); + preempt_disable(); + if (cmpxchg(&huge_zero_folio, NULL, zero_folio)) { + preempt_enable(); +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 92a2e8dcb79655..423d20453b90c9 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -3919,100 +3919,124 @@ static int set_max_huge_pages(struct hstate *h, unsigned long count, int nid, + return 0; + } + +-static int demote_free_hugetlb_folio(struct hstate *h, struct folio *folio) ++static long demote_free_hugetlb_folios(struct hstate *src, struct hstate *dst, ++ struct list_head *src_list) + { +- int i, nid = folio_nid(folio); +- struct hstate *target_hstate; +- struct page *subpage; +- struct folio *inner_folio; +- int rc = 0; +- +- target_hstate = size_to_hstate(PAGE_SIZE << h->demote_order); ++ long rc; ++ struct folio *folio, *next; ++ LIST_HEAD(dst_list); ++ LIST_HEAD(ret_list); + +- remove_hugetlb_folio(h, folio, false); +- spin_unlock_irq(&hugetlb_lock); +- +- /* +- * If vmemmap already existed for folio, the remove routine above would +- * have cleared the hugetlb folio flag. Hence the folio is technically +- * no longer a hugetlb folio. hugetlb_vmemmap_restore_folio can only be +- * passed hugetlb folios and will BUG otherwise. +- */ +- if (folio_test_hugetlb(folio)) { +- rc = hugetlb_vmemmap_restore_folio(h, folio); +- if (rc) { +- /* Allocation of vmemmmap failed, we can not demote folio */ +- spin_lock_irq(&hugetlb_lock); +- add_hugetlb_folio(h, folio, false); +- return rc; +- } +- } +- +- /* +- * Use destroy_compound_hugetlb_folio_for_demote for all huge page +- * sizes as it will not ref count folios. +- */ +- destroy_compound_hugetlb_folio_for_demote(folio, huge_page_order(h)); ++ rc = hugetlb_vmemmap_restore_folios(src, src_list, &ret_list); ++ list_splice_init(&ret_list, src_list); + + /* + * Taking target hstate mutex synchronizes with set_max_huge_pages. + * Without the mutex, pages added to target hstate could be marked + * as surplus. + * +- * Note that we already hold h->resize_lock. To prevent deadlock, ++ * Note that we already hold src->resize_lock. To prevent deadlock, + * use the convention of always taking larger size hstate mutex first. + */ +- mutex_lock(&target_hstate->resize_lock); +- for (i = 0; i < pages_per_huge_page(h); +- i += pages_per_huge_page(target_hstate)) { +- subpage = folio_page(folio, i); +- inner_folio = page_folio(subpage); +- if (hstate_is_gigantic(target_hstate)) +- prep_compound_gigantic_folio_for_demote(inner_folio, +- target_hstate->order); +- else +- prep_compound_page(subpage, target_hstate->order); +- folio_change_private(inner_folio, NULL); +- prep_new_hugetlb_folio(target_hstate, inner_folio, nid); +- free_huge_folio(inner_folio); ++ mutex_lock(&dst->resize_lock); ++ ++ list_for_each_entry_safe(folio, next, src_list, lru) { ++ int i; ++ ++ if (folio_test_hugetlb_vmemmap_optimized(folio)) ++ continue; ++ ++ list_del(&folio->lru); ++ /* ++ * Use destroy_compound_hugetlb_folio_for_demote for all huge page ++ * sizes as it will not ref count folios. ++ */ ++ destroy_compound_hugetlb_folio_for_demote(folio, huge_page_order(src)); ++ ++ for (i = 0; i < pages_per_huge_page(src); i += pages_per_huge_page(dst)) { ++ struct page *page = folio_page(folio, i); ++ ++ if (hstate_is_gigantic(dst)) ++ prep_compound_gigantic_folio_for_demote(page_folio(page), ++ dst->order); ++ else ++ prep_compound_page(page, dst->order); ++ set_page_private(page, 0); ++ ++ init_new_hugetlb_folio(dst, page_folio(page)); ++ list_add(&page->lru, &dst_list); ++ } + } +- mutex_unlock(&target_hstate->resize_lock); + +- spin_lock_irq(&hugetlb_lock); ++ prep_and_add_allocated_folios(dst, &dst_list); + +- /* +- * Not absolutely necessary, but for consistency update max_huge_pages +- * based on pool changes for the demoted page. +- */ +- h->max_huge_pages--; +- target_hstate->max_huge_pages += +- pages_per_huge_page(h) / pages_per_huge_page(target_hstate); ++ mutex_unlock(&dst->resize_lock); + + return rc; + } + +-static int demote_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed) ++static long demote_pool_huge_page(struct hstate *src, nodemask_t *nodes_allowed, ++ unsigned long nr_to_demote) + __must_hold(&hugetlb_lock) + { + int nr_nodes, node; +- struct folio *folio; ++ struct hstate *dst; ++ long rc = 0; ++ long nr_demoted = 0; + + lockdep_assert_held(&hugetlb_lock); + + /* We should never get here if no demote order */ +- if (!h->demote_order) { ++ if (!src->demote_order) { + pr_warn("HugeTLB: NULL demote order passed to demote_pool_huge_page.\n"); + return -EINVAL; /* internal error */ + } ++ dst = size_to_hstate(PAGE_SIZE << src->demote_order); + +- for_each_node_mask_to_free(h, nr_nodes, node, nodes_allowed) { +- list_for_each_entry(folio, &h->hugepage_freelists[node], lru) { ++ for_each_node_mask_to_free(src, nr_nodes, node, nodes_allowed) { ++ LIST_HEAD(list); ++ struct folio *folio, *next; ++ ++ list_for_each_entry_safe(folio, next, &src->hugepage_freelists[node], lru) { + if (folio_test_hwpoison(folio)) + continue; +- return demote_free_hugetlb_folio(h, folio); ++ ++ remove_hugetlb_folio(src, folio, false); ++ list_add(&folio->lru, &list); ++ ++ if (++nr_demoted == nr_to_demote) ++ break; + } ++ ++ spin_unlock_irq(&hugetlb_lock); ++ ++ rc = demote_free_hugetlb_folios(src, dst, &list); ++ ++ spin_lock_irq(&hugetlb_lock); ++ ++ list_for_each_entry_safe(folio, next, &list, lru) { ++ list_del(&folio->lru); ++ add_hugetlb_folio(src, folio, false); ++ ++ nr_demoted--; ++ } ++ ++ if (rc < 0 || nr_demoted == nr_to_demote) ++ break; + } + ++ /* ++ * Not absolutely necessary, but for consistency update max_huge_pages ++ * based on pool changes for the demoted page. ++ */ ++ src->max_huge_pages -= nr_demoted; ++ dst->max_huge_pages += nr_demoted << (huge_page_order(src) - huge_page_order(dst)); ++ ++ if (rc < 0) ++ return rc; ++ ++ if (nr_demoted) ++ return nr_demoted; + /* + * Only way to get here is if all pages on free lists are poisoned. + * Return -EBUSY so that caller will not retry. +@@ -4247,6 +4271,8 @@ static ssize_t demote_store(struct kobject *kobj, + spin_lock_irq(&hugetlb_lock); + + while (nr_demote) { ++ long rc; ++ + /* + * Check for available pages to demote each time thorough the + * loop as demote_pool_huge_page will drop hugetlb_lock. +@@ -4259,11 +4285,13 @@ static ssize_t demote_store(struct kobject *kobj, + if (!nr_available) + break; + +- err = demote_pool_huge_page(h, n_mask); +- if (err) ++ rc = demote_pool_huge_page(h, n_mask, nr_demote); ++ if (rc < 0) { ++ err = rc; + break; ++ } + +- nr_demote--; ++ nr_demote -= rc; + } + + spin_unlock_irq(&hugetlb_lock); +@@ -6047,7 +6075,7 @@ static vm_fault_t hugetlb_wp(struct folio *pagecache_folio, + * When the original hugepage is shared one, it does not have + * anon_vma prepared. + */ +- ret = vmf_anon_prepare(vmf); ++ ret = __vmf_anon_prepare(vmf); + if (unlikely(ret)) + goto out_release_all; + +@@ -6246,7 +6274,7 @@ static vm_fault_t hugetlb_no_page(struct address_space *mapping, + } + + if (!(vma->vm_flags & VM_MAYSHARE)) { +- ret = vmf_anon_prepare(vmf); ++ ret = __vmf_anon_prepare(vmf); + if (unlikely(ret)) + goto out; + } +@@ -6378,6 +6406,14 @@ static vm_fault_t hugetlb_no_page(struct address_space *mapping, + folio_unlock(folio); + out: + hugetlb_vma_unlock_read(vma); ++ ++ /* ++ * We must check to release the per-VMA lock. __vmf_anon_prepare() is ++ * the only way ret can be set to VM_FAULT_RETRY. ++ */ ++ if (unlikely(ret & VM_FAULT_RETRY)) ++ vma_end_read(vma); ++ + mutex_unlock(&hugetlb_fault_mutex_table[hash]); + return ret; + +@@ -6599,6 +6635,14 @@ vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, + } + out_mutex: + hugetlb_vma_unlock_read(vma); ++ ++ /* ++ * We must check to release the per-VMA lock. __vmf_anon_prepare() in ++ * hugetlb_wp() is the only way ret can be set to VM_FAULT_RETRY. ++ */ ++ if (unlikely(ret & VM_FAULT_RETRY)) ++ vma_end_read(vma); ++ + mutex_unlock(&hugetlb_fault_mutex_table[hash]); + /* + * Generally it's safe to hold refcount during waiting page lock. But +diff --git a/mm/internal.h b/mm/internal.h +index cc2c5e07fad3ba..6ef5eecabfc4f9 100644 +--- a/mm/internal.h ++++ b/mm/internal.h +@@ -293,7 +293,16 @@ static inline void wake_throttle_isolated(pg_data_t *pgdat) + wake_up(wqh); + } + +-vm_fault_t vmf_anon_prepare(struct vm_fault *vmf); ++vm_fault_t __vmf_anon_prepare(struct vm_fault *vmf); ++static inline vm_fault_t vmf_anon_prepare(struct vm_fault *vmf) ++{ ++ vm_fault_t ret = __vmf_anon_prepare(vmf); ++ ++ if (unlikely(ret & VM_FAULT_RETRY)) ++ vma_end_read(vmf->vma); ++ return ret; ++} ++ + vm_fault_t do_swap_page(struct vm_fault *vmf); + void folio_rotate_reclaimable(struct folio *folio); + bool __folio_end_writeback(struct folio *folio); +diff --git a/mm/memory.c b/mm/memory.c +index 7a898b85788dd9..cfc4df9fe99544 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -3226,7 +3226,7 @@ static inline vm_fault_t vmf_can_call_fault(const struct vm_fault *vmf) + } + + /** +- * vmf_anon_prepare - Prepare to handle an anonymous fault. ++ * __vmf_anon_prepare - Prepare to handle an anonymous fault. + * @vmf: The vm_fault descriptor passed from the fault handler. + * + * When preparing to insert an anonymous page into a VMA from a +@@ -3240,7 +3240,7 @@ static inline vm_fault_t vmf_can_call_fault(const struct vm_fault *vmf) + * Return: 0 if fault handling can proceed. Any other value should be + * returned to the caller. + */ +-vm_fault_t vmf_anon_prepare(struct vm_fault *vmf) ++vm_fault_t __vmf_anon_prepare(struct vm_fault *vmf) + { + struct vm_area_struct *vma = vmf->vma; + vm_fault_t ret = 0; +@@ -3248,10 +3248,8 @@ vm_fault_t vmf_anon_prepare(struct vm_fault *vmf) + if (likely(vma->anon_vma)) + return 0; + if (vmf->flags & FAULT_FLAG_VMA_LOCK) { +- if (!mmap_read_trylock(vma->vm_mm)) { +- vma_end_read(vma); ++ if (!mmap_read_trylock(vma->vm_mm)) + return VM_FAULT_RETRY; +- } + } + if (__anon_vma_prepare(vma)) + ret = VM_FAULT_OOM; +diff --git a/mm/migrate.c b/mm/migrate.c +index 9dabeb90f772d8..817019be893653 100644 +--- a/mm/migrate.c ++++ b/mm/migrate.c +@@ -1129,7 +1129,7 @@ static int migrate_folio_unmap(new_folio_t get_new_folio, + int rc = -EAGAIN; + int old_page_state = 0; + struct anon_vma *anon_vma = NULL; +- bool is_lru = !__folio_test_movable(src); ++ bool is_lru = data_race(!__folio_test_movable(src)); + bool locked = false; + bool dst_locked = false; + +diff --git a/mm/mmap.c b/mm/mmap.c +index 83b4682ec85cfa..47bd6f65f44139 100644 +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -3127,8 +3127,12 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, + flags |= MAP_LOCKED; + + file = get_file(vma->vm_file); ++ ret = security_mmap_file(vma->vm_file, prot, flags); ++ if (ret) ++ goto out_fput; + ret = do_mmap(vma->vm_file, start, size, + prot, flags, 0, pgoff, &populate, NULL); ++out_fput: + fput(file); + out: + mmap_write_unlock(mm); +diff --git a/mm/util.c b/mm/util.c +index fe723241b66f73..37a5d75f8adf05 100644 +--- a/mm/util.c ++++ b/mm/util.c +@@ -451,7 +451,7 @@ static unsigned long mmap_base(unsigned long rnd, struct rlimit *rlim_stack) + if (gap + pad > gap) + gap += pad; + +- if (gap < MIN_GAP) ++ if (gap < MIN_GAP && MIN_GAP < MAX_GAP) + gap = MIN_GAP; + else if (gap > MAX_GAP) + gap = MAX_GAP; +diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c +index 3c74d171085deb..bfa773730f3bd7 100644 +--- a/net/bluetooth/hci_conn.c ++++ b/net/bluetooth/hci_conn.c +@@ -107,8 +107,7 @@ void hci_connect_le_scan_cleanup(struct hci_conn *conn, u8 status) + * where a timeout + cancel does indicate an actual failure. + */ + if (status && status != HCI_ERROR_UNKNOWN_CONN_ID) +- mgmt_connect_failed(hdev, &conn->dst, conn->type, +- conn->dst_type, status); ++ mgmt_connect_failed(hdev, conn, status); + + /* The connection attempt was doing scan for new RPA, and is + * in scan phase. If params are not associated with any other +@@ -1251,8 +1250,7 @@ void hci_conn_failed(struct hci_conn *conn, u8 status) + hci_le_conn_failed(conn, status); + break; + case ACL_LINK: +- mgmt_connect_failed(hdev, &conn->dst, conn->type, +- conn->dst_type, status); ++ mgmt_connect_failed(hdev, conn, status); + break; + } + +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index f4a54dbc07f19a..86fee9d6c14248 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -5331,7 +5331,10 @@ int hci_stop_discovery_sync(struct hci_dev *hdev) + if (!e) + return 0; + +- return hci_remote_name_cancel_sync(hdev, &e->data.bdaddr); ++ /* Ignore cancel errors since it should interfere with stopping ++ * of the discovery. ++ */ ++ hci_remote_name_cancel_sync(hdev, &e->data.bdaddr); + } + + return 0; +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index ba28907afb3fa6..c383eb44d516bc 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -9734,13 +9734,18 @@ void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, + mgmt_pending_remove(cmd); + } + +-void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, +- u8 addr_type, u8 status) ++void mgmt_connect_failed(struct hci_dev *hdev, struct hci_conn *conn, u8 status) + { + struct mgmt_ev_connect_failed ev; + +- bacpy(&ev.addr.bdaddr, bdaddr); +- ev.addr.type = link_to_bdaddr(link_type, addr_type); ++ if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { ++ mgmt_device_disconnected(hdev, &conn->dst, conn->type, ++ conn->dst_type, status, true); ++ return; ++ } ++ ++ bacpy(&ev.addr.bdaddr, &conn->dst); ++ ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type); + ev.status = mgmt_status(status); + + mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL); +diff --git a/net/can/bcm.c b/net/can/bcm.c +index 46d3ec3aa44b4a..217049fa496e9d 100644 +--- a/net/can/bcm.c ++++ b/net/can/bcm.c +@@ -1471,8 +1471,10 @@ static void bcm_notify(struct bcm_sock *bo, unsigned long msg, + /* remove device reference, if this is our bound device */ + if (bo->bound && bo->ifindex == dev->ifindex) { + #if IS_ENABLED(CONFIG_PROC_FS) +- if (sock_net(sk)->can.bcmproc_dir && bo->bcm_proc_read) ++ if (sock_net(sk)->can.bcmproc_dir && bo->bcm_proc_read) { + remove_proc_entry(bo->procname, sock_net(sk)->can.bcmproc_dir); ++ bo->bcm_proc_read = NULL; ++ } + #endif + bo->bound = 0; + bo->ifindex = 0; +diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c +index 4be73de5033cb7..319f47df33300c 100644 +--- a/net/can/j1939/transport.c ++++ b/net/can/j1939/transport.c +@@ -1179,10 +1179,10 @@ static enum hrtimer_restart j1939_tp_txtimer(struct hrtimer *hrtimer) + break; + case -ENETDOWN: + /* In this case we should get a netdev_event(), all active +- * sessions will be cleared by +- * j1939_cancel_all_active_sessions(). So handle this as an +- * error, but let j1939_cancel_all_active_sessions() do the +- * cleanup including propagation of the error to user space. ++ * sessions will be cleared by j1939_cancel_active_session(). ++ * So handle this as an error, but let ++ * j1939_cancel_active_session() do the cleanup including ++ * propagation of the error to user space. + */ + break; + case -EOVERFLOW: +diff --git a/net/core/filter.c b/net/core/filter.c +index 55b1d9de2334db..61da5512cd4d2a 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -6258,20 +6258,25 @@ BPF_CALL_5(bpf_skb_check_mtu, struct sk_buff *, skb, + int ret = BPF_MTU_CHK_RET_FRAG_NEEDED; + struct net_device *dev = skb->dev; + int skb_len, dev_len; +- int mtu; ++ int mtu = 0; + +- if (unlikely(flags & ~(BPF_MTU_CHK_SEGS))) +- return -EINVAL; ++ if (unlikely(flags & ~(BPF_MTU_CHK_SEGS))) { ++ ret = -EINVAL; ++ goto out; ++ } + +- if (unlikely(flags & BPF_MTU_CHK_SEGS && (len_diff || *mtu_len))) +- return -EINVAL; ++ if (unlikely(flags & BPF_MTU_CHK_SEGS && (len_diff || *mtu_len))) { ++ ret = -EINVAL; ++ goto out; ++ } + + dev = __dev_via_ifindex(dev, ifindex); +- if (unlikely(!dev)) +- return -ENODEV; ++ if (unlikely(!dev)) { ++ ret = -ENODEV; ++ goto out; ++ } + + mtu = READ_ONCE(dev->mtu); +- + dev_len = mtu + dev->hard_header_len; + + /* If set use *mtu_len as input, L3 as iph->tot_len (like fib_lookup) */ +@@ -6289,15 +6294,12 @@ BPF_CALL_5(bpf_skb_check_mtu, struct sk_buff *, skb, + */ + if (skb_is_gso(skb)) { + ret = BPF_MTU_CHK_RET_SUCCESS; +- + if (flags & BPF_MTU_CHK_SEGS && + !skb_gso_validate_network_len(skb, mtu)) + ret = BPF_MTU_CHK_RET_SEGS_TOOBIG; + } + out: +- /* BPF verifier guarantees valid pointer */ + *mtu_len = mtu; +- + return ret; + } + +@@ -6307,19 +6309,21 @@ BPF_CALL_5(bpf_xdp_check_mtu, struct xdp_buff *, xdp, + struct net_device *dev = xdp->rxq->dev; + int xdp_len = xdp->data_end - xdp->data; + int ret = BPF_MTU_CHK_RET_SUCCESS; +- int mtu, dev_len; ++ int mtu = 0, dev_len; + + /* XDP variant doesn't support multi-buffer segment check (yet) */ +- if (unlikely(flags)) +- return -EINVAL; ++ if (unlikely(flags)) { ++ ret = -EINVAL; ++ goto out; ++ } + + dev = __dev_via_ifindex(dev, ifindex); +- if (unlikely(!dev)) +- return -ENODEV; ++ if (unlikely(!dev)) { ++ ret = -ENODEV; ++ goto out; ++ } + + mtu = READ_ONCE(dev->mtu); +- +- /* Add L2-header as dev MTU is L3 size */ + dev_len = mtu + dev->hard_header_len; + + /* Use *mtu_len as input, L3 as iph->tot_len (like fib_lookup) */ +@@ -6329,10 +6333,8 @@ BPF_CALL_5(bpf_xdp_check_mtu, struct xdp_buff *, xdp, + xdp_len += len_diff; /* minus result pass check */ + if (xdp_len > dev_len) + ret = BPF_MTU_CHK_RET_FRAG_NEEDED; +- +- /* BPF verifier guarantees valid pointer */ ++out: + *mtu_len = mtu; +- + return ret; + } + +@@ -6342,7 +6344,8 @@ static const struct bpf_func_proto bpf_skb_check_mtu_proto = { + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, +- .arg3_type = ARG_PTR_TO_INT, ++ .arg3_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_ALIGNED, ++ .arg3_size = sizeof(u32), + .arg4_type = ARG_ANYTHING, + .arg5_type = ARG_ANYTHING, + }; +@@ -6353,7 +6356,8 @@ static const struct bpf_func_proto bpf_xdp_check_mtu_proto = { + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, +- .arg3_type = ARG_PTR_TO_INT, ++ .arg3_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_ALIGNED, ++ .arg3_size = sizeof(u32), + .arg4_type = ARG_ANYTHING, + .arg5_type = ARG_ANYTHING, + }; +@@ -8568,13 +8572,16 @@ static bool bpf_skb_is_valid_access(int off, int size, enum bpf_access_type type + if (off + size > offsetofend(struct __sk_buff, cb[4])) + return false; + break; ++ case bpf_ctx_range(struct __sk_buff, data): ++ case bpf_ctx_range(struct __sk_buff, data_meta): ++ case bpf_ctx_range(struct __sk_buff, data_end): ++ if (info->is_ldsx || size != size_default) ++ return false; ++ break; + case bpf_ctx_range_till(struct __sk_buff, remote_ip6[0], remote_ip6[3]): + case bpf_ctx_range_till(struct __sk_buff, local_ip6[0], local_ip6[3]): + case bpf_ctx_range_till(struct __sk_buff, remote_ip4, remote_ip4): + case bpf_ctx_range_till(struct __sk_buff, local_ip4, local_ip4): +- case bpf_ctx_range(struct __sk_buff, data): +- case bpf_ctx_range(struct __sk_buff, data_meta): +- case bpf_ctx_range(struct __sk_buff, data_end): + if (size != size_default) + return false; + break; +@@ -9018,6 +9025,14 @@ static bool xdp_is_valid_access(int off, int size, + } + } + return false; ++ } else { ++ switch (off) { ++ case offsetof(struct xdp_md, data_meta): ++ case offsetof(struct xdp_md, data): ++ case offsetof(struct xdp_md, data_end): ++ if (info->is_ldsx) ++ return false; ++ } + } + + switch (off) { +@@ -9343,12 +9358,12 @@ static bool flow_dissector_is_valid_access(int off, int size, + + switch (off) { + case bpf_ctx_range(struct __sk_buff, data): +- if (size != size_default) ++ if (info->is_ldsx || size != size_default) + return false; + info->reg_type = PTR_TO_PACKET; + return true; + case bpf_ctx_range(struct __sk_buff, data_end): +- if (size != size_default) ++ if (info->is_ldsx || size != size_default) + return false; + info->reg_type = PTR_TO_PACKET_END; + return true; +diff --git a/net/core/sock_map.c b/net/core/sock_map.c +index d3dbb92153f2fe..724b6856fcc3e9 100644 +--- a/net/core/sock_map.c ++++ b/net/core/sock_map.c +@@ -1183,6 +1183,7 @@ static void sock_hash_free(struct bpf_map *map) + sock_put(elem->sk); + sock_hash_free_elem(htab, elem); + } ++ cond_resched(); + } + + /* wait for psock readers accessing its map link */ +diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c +index af6cf64a00e081..464f683e016dbb 100644 +--- a/net/hsr/hsr_slave.c ++++ b/net/hsr/hsr_slave.c +@@ -67,7 +67,16 @@ static rx_handler_result_t hsr_handle_frame(struct sk_buff **pskb) + skb_set_network_header(skb, ETH_HLEN + HSR_HLEN); + skb_reset_mac_len(skb); + +- hsr_forward_skb(skb, port); ++ /* Only the frames received over the interlink port will assign a ++ * sequence number and require synchronisation vs other sender. ++ */ ++ if (port->type == HSR_PT_INTERLINK) { ++ spin_lock_bh(&hsr->seqnr_lock); ++ hsr_forward_skb(skb, port); ++ spin_unlock_bh(&hsr->seqnr_lock); ++ } else { ++ hsr_forward_skb(skb, port); ++ } + + finish_consume: + return RX_HANDLER_CONSUMED; +diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c +index ab6d0d98dbc34c..336518e623b280 100644 +--- a/net/ipv4/icmp.c ++++ b/net/ipv4/icmp.c +@@ -224,57 +224,59 @@ int sysctl_icmp_msgs_per_sec __read_mostly = 1000; + int sysctl_icmp_msgs_burst __read_mostly = 50; + + static struct { +- spinlock_t lock; +- u32 credit; ++ atomic_t credit; + u32 stamp; +-} icmp_global = { +- .lock = __SPIN_LOCK_UNLOCKED(icmp_global.lock), +-}; ++} icmp_global; + + /** + * icmp_global_allow - Are we allowed to send one more ICMP message ? + * + * Uses a token bucket to limit our ICMP messages to ~sysctl_icmp_msgs_per_sec. + * Returns false if we reached the limit and can not send another packet. +- * Note: called with BH disabled ++ * Works in tandem with icmp_global_consume(). + */ + bool icmp_global_allow(void) + { +- u32 credit, delta, incr = 0, now = (u32)jiffies; +- bool rc = false; ++ u32 delta, now, oldstamp; ++ int incr, new, old; + +- /* Check if token bucket is empty and cannot be refilled +- * without taking the spinlock. The READ_ONCE() are paired +- * with the following WRITE_ONCE() in this same function. ++ /* Note: many cpus could find this condition true. ++ * Then later icmp_global_consume() could consume more credits, ++ * this is an acceptable race. + */ +- if (!READ_ONCE(icmp_global.credit)) { +- delta = min_t(u32, now - READ_ONCE(icmp_global.stamp), HZ); +- if (delta < HZ / 50) +- return false; +- } ++ if (atomic_read(&icmp_global.credit) > 0) ++ return true; + +- spin_lock(&icmp_global.lock); +- delta = min_t(u32, now - icmp_global.stamp, HZ); +- if (delta >= HZ / 50) { +- incr = READ_ONCE(sysctl_icmp_msgs_per_sec) * delta / HZ; +- if (incr) +- WRITE_ONCE(icmp_global.stamp, now); +- } +- credit = min_t(u32, icmp_global.credit + incr, +- READ_ONCE(sysctl_icmp_msgs_burst)); +- if (credit) { +- /* We want to use a credit of one in average, but need to randomize +- * it for security reasons. +- */ +- credit = max_t(int, credit - get_random_u32_below(3), 0); +- rc = true; ++ now = jiffies; ++ oldstamp = READ_ONCE(icmp_global.stamp); ++ delta = min_t(u32, now - oldstamp, HZ); ++ if (delta < HZ / 50) ++ return false; ++ ++ incr = READ_ONCE(sysctl_icmp_msgs_per_sec) * delta / HZ; ++ if (!incr) ++ return false; ++ ++ if (cmpxchg(&icmp_global.stamp, oldstamp, now) == oldstamp) { ++ old = atomic_read(&icmp_global.credit); ++ do { ++ new = min(old + incr, READ_ONCE(sysctl_icmp_msgs_burst)); ++ } while (!atomic_try_cmpxchg(&icmp_global.credit, &old, new)); + } +- WRITE_ONCE(icmp_global.credit, credit); +- spin_unlock(&icmp_global.lock); +- return rc; ++ return true; + } + EXPORT_SYMBOL(icmp_global_allow); + ++void icmp_global_consume(void) ++{ ++ int credits = get_random_u32_below(3); ++ ++ /* Note: this might make icmp_global.credit negative. */ ++ if (credits) ++ atomic_sub(credits, &icmp_global.credit); ++} ++EXPORT_SYMBOL(icmp_global_consume); ++ + static bool icmpv4_mask_allow(struct net *net, int type, int code) + { + if (type > NR_ICMP_TYPES) +@@ -291,14 +293,16 @@ static bool icmpv4_mask_allow(struct net *net, int type, int code) + return false; + } + +-static bool icmpv4_global_allow(struct net *net, int type, int code) ++static bool icmpv4_global_allow(struct net *net, int type, int code, ++ bool *apply_ratelimit) + { + if (icmpv4_mask_allow(net, type, code)) + return true; + +- if (icmp_global_allow()) ++ if (icmp_global_allow()) { ++ *apply_ratelimit = true; + return true; +- ++ } + __ICMP_INC_STATS(net, ICMP_MIB_RATELIMITGLOBAL); + return false; + } +@@ -308,15 +312,16 @@ static bool icmpv4_global_allow(struct net *net, int type, int code) + */ + + static bool icmpv4_xrlim_allow(struct net *net, struct rtable *rt, +- struct flowi4 *fl4, int type, int code) ++ struct flowi4 *fl4, int type, int code, ++ bool apply_ratelimit) + { + struct dst_entry *dst = &rt->dst; + struct inet_peer *peer; + bool rc = true; + int vif; + +- if (icmpv4_mask_allow(net, type, code)) +- goto out; ++ if (!apply_ratelimit) ++ return true; + + /* No rate limit on loopback */ + if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) +@@ -331,6 +336,8 @@ static bool icmpv4_xrlim_allow(struct net *net, struct rtable *rt, + out: + if (!rc) + __ICMP_INC_STATS(net, ICMP_MIB_RATELIMITHOST); ++ else ++ icmp_global_consume(); + return rc; + } + +@@ -402,6 +409,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) + struct ipcm_cookie ipc; + struct rtable *rt = skb_rtable(skb); + struct net *net = dev_net(rt->dst.dev); ++ bool apply_ratelimit = false; + struct flowi4 fl4; + struct sock *sk; + struct inet_sock *inet; +@@ -413,11 +421,11 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) + if (ip_options_echo(net, &icmp_param->replyopts.opt.opt, skb)) + return; + +- /* Needed by both icmp_global_allow and icmp_xmit_lock */ ++ /* Needed by both icmpv4_global_allow and icmp_xmit_lock */ + local_bh_disable(); + +- /* global icmp_msgs_per_sec */ +- if (!icmpv4_global_allow(net, type, code)) ++ /* is global icmp_msgs_per_sec exhausted ? */ ++ if (!icmpv4_global_allow(net, type, code, &apply_ratelimit)) + goto out_bh_enable; + + sk = icmp_xmit_lock(net); +@@ -450,7 +458,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) + rt = ip_route_output_key(net, &fl4); + if (IS_ERR(rt)) + goto out_unlock; +- if (icmpv4_xrlim_allow(net, rt, &fl4, type, code)) ++ if (icmpv4_xrlim_allow(net, rt, &fl4, type, code, apply_ratelimit)) + icmp_push_reply(sk, icmp_param, &fl4, &ipc, &rt); + ip_rt_put(rt); + out_unlock: +@@ -596,6 +604,7 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info, + int room; + struct icmp_bxm icmp_param; + struct rtable *rt = skb_rtable(skb_in); ++ bool apply_ratelimit = false; + struct ipcm_cookie ipc; + struct flowi4 fl4; + __be32 saddr; +@@ -677,7 +686,7 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info, + } + } + +- /* Needed by both icmp_global_allow and icmp_xmit_lock */ ++ /* Needed by both icmpv4_global_allow and icmp_xmit_lock */ + local_bh_disable(); + + /* Check global sysctl_icmp_msgs_per_sec ratelimit, unless +@@ -685,7 +694,7 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info, + * loopback, then peer ratelimit still work (in icmpv4_xrlim_allow) + */ + if (!(skb_in->dev && (skb_in->dev->flags&IFF_LOOPBACK)) && +- !icmpv4_global_allow(net, type, code)) ++ !icmpv4_global_allow(net, type, code, &apply_ratelimit)) + goto out_bh_enable; + + sk = icmp_xmit_lock(net); +@@ -744,7 +753,7 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info, + goto out_unlock; + + /* peer icmp_ratelimit */ +- if (!icmpv4_xrlim_allow(net, rt, &fl4, type, code)) ++ if (!icmpv4_xrlim_allow(net, rt, &fl4, type, code, apply_ratelimit)) + goto ende; + + /* RFC says return as much as we can without exceeding 576 bytes. */ +diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig +index 08d4b7132d4c45..1c9c686d9522f7 100644 +--- a/net/ipv6/Kconfig ++++ b/net/ipv6/Kconfig +@@ -323,6 +323,7 @@ config IPV6_RPL_LWTUNNEL + bool "IPv6: RPL Source Routing Header support" + depends on IPV6 + select LWTUNNEL ++ select DST_CACHE + help + Support for RFC6554 RPL Source Routing Header using the lightweight + tunnels mechanism. +diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c +index 7b31674644efc3..46f70e4a835139 100644 +--- a/net/ipv6/icmp.c ++++ b/net/ipv6/icmp.c +@@ -175,14 +175,16 @@ static bool icmpv6_mask_allow(struct net *net, int type) + return false; + } + +-static bool icmpv6_global_allow(struct net *net, int type) ++static bool icmpv6_global_allow(struct net *net, int type, ++ bool *apply_ratelimit) + { + if (icmpv6_mask_allow(net, type)) + return true; + +- if (icmp_global_allow()) ++ if (icmp_global_allow()) { ++ *apply_ratelimit = true; + return true; +- ++ } + __ICMP_INC_STATS(net, ICMP_MIB_RATELIMITGLOBAL); + return false; + } +@@ -191,13 +193,13 @@ static bool icmpv6_global_allow(struct net *net, int type) + * Check the ICMP output rate limit + */ + static bool icmpv6_xrlim_allow(struct sock *sk, u8 type, +- struct flowi6 *fl6) ++ struct flowi6 *fl6, bool apply_ratelimit) + { + struct net *net = sock_net(sk); + struct dst_entry *dst; + bool res = false; + +- if (icmpv6_mask_allow(net, type)) ++ if (!apply_ratelimit) + return true; + + /* +@@ -228,6 +230,8 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type, + if (!res) + __ICMP6_INC_STATS(net, ip6_dst_idev(dst), + ICMP6_MIB_RATELIMITHOST); ++ else ++ icmp_global_consume(); + dst_release(dst); + return res; + } +@@ -452,6 +456,7 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, + struct net *net; + struct ipv6_pinfo *np; + const struct in6_addr *saddr = NULL; ++ bool apply_ratelimit = false; + struct dst_entry *dst; + struct icmp6hdr tmp_hdr; + struct flowi6 fl6; +@@ -533,11 +538,12 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, + return; + } + +- /* Needed by both icmp_global_allow and icmpv6_xmit_lock */ ++ /* Needed by both icmpv6_global_allow and icmpv6_xmit_lock */ + local_bh_disable(); + + /* Check global sysctl_icmp_msgs_per_sec ratelimit */ +- if (!(skb->dev->flags & IFF_LOOPBACK) && !icmpv6_global_allow(net, type)) ++ if (!(skb->dev->flags & IFF_LOOPBACK) && ++ !icmpv6_global_allow(net, type, &apply_ratelimit)) + goto out_bh_enable; + + mip6_addr_swap(skb, parm); +@@ -575,7 +581,7 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, + + np = inet6_sk(sk); + +- if (!icmpv6_xrlim_allow(sk, type, &fl6)) ++ if (!icmpv6_xrlim_allow(sk, type, &fl6, apply_ratelimit)) + goto out; + + tmp_hdr.icmp6_type = type; +@@ -717,6 +723,7 @@ static enum skb_drop_reason icmpv6_echo_reply(struct sk_buff *skb) + struct ipv6_pinfo *np; + const struct in6_addr *saddr = NULL; + struct icmp6hdr *icmph = icmp6_hdr(skb); ++ bool apply_ratelimit = false; + struct icmp6hdr tmp_hdr; + struct flowi6 fl6; + struct icmpv6_msg msg; +@@ -781,8 +788,9 @@ static enum skb_drop_reason icmpv6_echo_reply(struct sk_buff *skb) + goto out; + + /* Check the ratelimit */ +- if ((!(skb->dev->flags & IFF_LOOPBACK) && !icmpv6_global_allow(net, ICMPV6_ECHO_REPLY)) || +- !icmpv6_xrlim_allow(sk, ICMPV6_ECHO_REPLY, &fl6)) ++ if ((!(skb->dev->flags & IFF_LOOPBACK) && ++ !icmpv6_global_allow(net, ICMPV6_ECHO_REPLY, &apply_ratelimit)) || ++ !icmpv6_xrlim_allow(sk, ICMPV6_ECHO_REPLY, &fl6, apply_ratelimit)) + goto out_dst_release; + + idev = __in6_dev_get(skb->dev); +diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c +index dedee264b8f6c8..b9457473c176df 100644 +--- a/net/ipv6/netfilter/nf_reject_ipv6.c ++++ b/net/ipv6/netfilter/nf_reject_ipv6.c +@@ -223,33 +223,23 @@ void nf_reject_ip6_tcphdr_put(struct sk_buff *nskb, + const struct tcphdr *oth, unsigned int otcplen) + { + struct tcphdr *tcph; +- int needs_ack; + + skb_reset_transport_header(nskb); +- tcph = skb_put(nskb, sizeof(struct tcphdr)); ++ tcph = skb_put_zero(nskb, sizeof(struct tcphdr)); + /* Truncate to length (no data) */ + tcph->doff = sizeof(struct tcphdr)/4; + tcph->source = oth->dest; + tcph->dest = oth->source; + + if (oth->ack) { +- needs_ack = 0; + tcph->seq = oth->ack_seq; +- tcph->ack_seq = 0; + } else { +- needs_ack = 1; + tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin + + otcplen - (oth->doff<<2)); +- tcph->seq = 0; ++ tcph->ack = 1; + } + +- /* Reset flags */ +- ((u_int8_t *)tcph)[13] = 0; + tcph->rst = 1; +- tcph->ack = needs_ack; +- tcph->window = 0; +- tcph->urg_ptr = 0; +- tcph->check = 0; + + /* Adjust TCP checksum */ + tcph->check = csum_ipv6_magic(&ipv6_hdr(nskb)->saddr, +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index a9644a8edb9609..1febd95822c9a7 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -175,7 +175,7 @@ static void rt6_uncached_list_flush_dev(struct net_device *dev) + struct net_device *rt_dev = rt->dst.dev; + bool handled = false; + +- if (rt_idev->dev == dev) { ++ if (rt_idev && rt_idev->dev == dev) { + rt->rt6i_idev = in6_dev_get(blackhole_netdev); + in6_dev_put(rt_idev); + handled = true; +diff --git a/net/ipv6/rpl_iptunnel.c b/net/ipv6/rpl_iptunnel.c +index 2c83b7586422dd..db3c19a42e1ca7 100644 +--- a/net/ipv6/rpl_iptunnel.c ++++ b/net/ipv6/rpl_iptunnel.c +@@ -263,10 +263,8 @@ static int rpl_input(struct sk_buff *skb) + rlwt = rpl_lwt_lwtunnel(orig_dst->lwtstate); + + err = rpl_do_srh(skb, rlwt); +- if (unlikely(err)) { +- kfree_skb(skb); +- return err; +- } ++ if (unlikely(err)) ++ goto drop; + + local_bh_disable(); + dst = dst_cache_get(&rlwt->cache); +@@ -286,9 +284,13 @@ static int rpl_input(struct sk_buff *skb) + + err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev)); + if (unlikely(err)) +- return err; ++ goto drop; + + return dst_input(skb); ++ ++drop: ++ kfree_skb(skb); ++ return err; + } + + static int nla_put_rpl_srh(struct sk_buff *skb, int attrtype, +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index b935bb5d8ed1f7..3e3814076006e6 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -462,6 +462,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do + { + struct ieee80211_local *local = sdata->local; + unsigned long flags; ++ struct sk_buff_head freeq; + struct sk_buff *skb, *tmp; + u32 hw_reconf_flags = 0; + int i, flushed; +@@ -641,18 +642,32 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do + skb_queue_purge(&sdata->status_queue); + } + ++ /* ++ * Since ieee80211_free_txskb() may issue __dev_queue_xmit() ++ * which should be called with interrupts enabled, reclamation ++ * is done in two phases: ++ */ ++ __skb_queue_head_init(&freeq); ++ ++ /* unlink from local queues... */ + spin_lock_irqsave(&local->queue_stop_reason_lock, flags); + for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { + skb_queue_walk_safe(&local->pending[i], skb, tmp) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + if (info->control.vif == &sdata->vif) { + __skb_unlink(skb, &local->pending[i]); +- ieee80211_free_txskb(&local->hw, skb); ++ __skb_queue_tail(&freeq, skb); + } + } + } + spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); + ++ /* ... and perform actual reclamation with interrupts enabled. */ ++ skb_queue_walk_safe(&freeq, skb, tmp) { ++ __skb_unlink(skb, &freeq); ++ ieee80211_free_txskb(&local->hw, skb); ++ } ++ + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + ieee80211_txq_remove_vlan(local, sdata); + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index ad2ce9c92ba8a2..1faf4d7c115f08 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -4317,7 +4317,7 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link, + ((assoc_data->wmm && !elems->wmm_param) || + (link->u.mgd.conn.mode >= IEEE80211_CONN_MODE_HT && + (!elems->ht_cap_elem || !elems->ht_operation)) || +- (link->u.mgd.conn.mode >= IEEE80211_CONN_MODE_VHT && ++ (is_5ghz && link->u.mgd.conn.mode >= IEEE80211_CONN_MODE_VHT && + (!elems->vht_cap_elem || !elems->vht_operation)))) { + const struct cfg80211_bss_ies *ies; + struct ieee802_11_elems *bss_elems; +@@ -4365,19 +4365,22 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link, + sdata_info(sdata, + "AP bug: HT operation missing from AssocResp\n"); + } +- if (!elems->vht_cap_elem && bss_elems->vht_cap_elem && +- link->u.mgd.conn.mode >= IEEE80211_CONN_MODE_VHT) { +- elems->vht_cap_elem = bss_elems->vht_cap_elem; +- sdata_info(sdata, +- "AP bug: VHT capa missing from AssocResp\n"); +- } +- if (!elems->vht_operation && bss_elems->vht_operation && +- link->u.mgd.conn.mode >= IEEE80211_CONN_MODE_VHT) { +- elems->vht_operation = bss_elems->vht_operation; +- sdata_info(sdata, +- "AP bug: VHT operation missing from AssocResp\n"); +- } + ++ if (is_5ghz) { ++ if (!elems->vht_cap_elem && bss_elems->vht_cap_elem && ++ link->u.mgd.conn.mode >= IEEE80211_CONN_MODE_VHT) { ++ elems->vht_cap_elem = bss_elems->vht_cap_elem; ++ sdata_info(sdata, ++ "AP bug: VHT capa missing from AssocResp\n"); ++ } ++ ++ if (!elems->vht_operation && bss_elems->vht_operation && ++ link->u.mgd.conn.mode >= IEEE80211_CONN_MODE_VHT) { ++ elems->vht_operation = bss_elems->vht_operation; ++ sdata_info(sdata, ++ "AP bug: VHT operation missing from AssocResp\n"); ++ } ++ } + kfree(bss_elems); + } + +@@ -7121,6 +7124,7 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata) + lockdep_assert_wiphy(sdata->local->hw.wiphy); + + assoc_data->tries++; ++ assoc_data->comeback = false; + if (assoc_data->tries > IEEE80211_ASSOC_MAX_TRIES) { + sdata_info(sdata, "association with %pM timed out\n", + assoc_data->ap_addr); +diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c +index 65e1e9e971fd69..5810d938edc44c 100644 +--- a/net/mac80211/offchannel.c ++++ b/net/mac80211/offchannel.c +@@ -964,6 +964,7 @@ int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, + } + + IEEE80211_SKB_CB(skb)->flags = flags; ++ IEEE80211_SKB_CB(skb)->control.flags |= IEEE80211_TX_CTRL_DONT_USE_RATE_MASK; + + skb->dev = sdata->dev; + +diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c +index 4dc1def6954865..3dc9752188d58f 100644 +--- a/net/mac80211/rate.c ++++ b/net/mac80211/rate.c +@@ -890,7 +890,7 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif, + if (ieee80211_is_tx_data(skb)) + rate_control_apply_mask(sdata, sta, sband, dest, max_rates); + +- if (!(info->control.flags & IEEE80211_TX_CTRL_SCAN_TX)) ++ if (!(info->control.flags & IEEE80211_TX_CTRL_DONT_USE_RATE_MASK)) + mask = sdata->rc_rateidx_mask[info->band]; + + if (dest[0].idx < 0) +diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c +index b5f2df61c7f671..1c5d99975ad04d 100644 +--- a/net/mac80211/scan.c ++++ b/net/mac80211/scan.c +@@ -649,7 +649,7 @@ static void ieee80211_send_scan_probe_req(struct ieee80211_sub_if_data *sdata, + cpu_to_le16(IEEE80211_SN_TO_SEQ(sn)); + } + IEEE80211_SKB_CB(skb)->flags |= tx_flags; +- IEEE80211_SKB_CB(skb)->control.flags |= IEEE80211_TX_CTRL_SCAN_TX; ++ IEEE80211_SKB_CB(skb)->control.flags |= IEEE80211_TX_CTRL_DONT_USE_RATE_MASK; + ieee80211_tx_skb_tid_band(sdata, skb, 7, channel->band); + } + } +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index bca7b341dd772d..a9ee8698225929 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -699,7 +699,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) + txrc.skb = tx->skb; + txrc.reported_rate.idx = -1; + +- if (unlikely(info->control.flags & IEEE80211_TX_CTRL_SCAN_TX)) { ++ if (unlikely(info->control.flags & IEEE80211_TX_CTRL_DONT_USE_RATE_MASK)) { + txrc.rate_idx_mask = ~0; + } else { + txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[info->band]; +diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c +index 4cbf71d0786b0d..c55cf5bc36b2f2 100644 +--- a/net/netfilter/nf_conntrack_netlink.c ++++ b/net/netfilter/nf_conntrack_netlink.c +@@ -382,7 +382,7 @@ static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct) + #define ctnetlink_dump_secctx(a, b) (0) + #endif + +-#ifdef CONFIG_NF_CONNTRACK_LABELS ++#ifdef CONFIG_NF_CONNTRACK_EVENTS + static inline int ctnetlink_label_size(const struct nf_conn *ct) + { + struct nf_conn_labels *labels = nf_ct_labels_find(ct); +@@ -391,6 +391,7 @@ static inline int ctnetlink_label_size(const struct nf_conn *ct) + return 0; + return nla_total_size(sizeof(labels->bits)); + } ++#endif + + static int + ctnetlink_dump_labels(struct sk_buff *skb, const struct nf_conn *ct) +@@ -411,10 +412,6 @@ ctnetlink_dump_labels(struct sk_buff *skb, const struct nf_conn *ct) + + return 0; + } +-#else +-#define ctnetlink_dump_labels(a, b) (0) +-#define ctnetlink_label_size(a) (0) +-#endif + + #define master_tuple(ct) &(ct->master->tuplehash[IP_CT_DIR_ORIGINAL].tuple) + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index 41d7faeb101cfc..465cc43c75e30e 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -1795,7 +1795,7 @@ static int nft_dump_basechain_hook(struct sk_buff *skb, int family, + if (!hook_list) + hook_list = &basechain->hook_list; + +- list_for_each_entry(hook, hook_list, list) { ++ list_for_each_entry_rcu(hook, hook_list, list) { + if (!first) + first = hook; + +@@ -4544,7 +4544,7 @@ int nf_msecs_to_jiffies64(const struct nlattr *nla, u64 *result) + return -ERANGE; + + ms *= NSEC_PER_MSEC; +- *result = nsecs_to_jiffies64(ms); ++ *result = nsecs_to_jiffies64(ms) ? : !!ms; + return 0; + } + +@@ -6631,7 +6631,7 @@ static int nft_setelem_catchall_insert(const struct net *net, + } + } + +- catchall = kmalloc(sizeof(*catchall), GFP_KERNEL); ++ catchall = kmalloc(sizeof(*catchall), GFP_KERNEL_ACCOUNT); + if (!catchall) + return -ENOMEM; + +@@ -6867,17 +6867,23 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, + return err; + } else if (set->flags & NFT_SET_TIMEOUT && + !(flags & NFT_SET_ELEM_INTERVAL_END)) { +- timeout = READ_ONCE(set->timeout); ++ timeout = set->timeout; + } + + expiration = 0; + if (nla[NFTA_SET_ELEM_EXPIRATION] != NULL) { + if (!(set->flags & NFT_SET_TIMEOUT)) + return -EINVAL; ++ if (timeout == 0) ++ return -EOPNOTSUPP; ++ + err = nf_msecs_to_jiffies64(nla[NFTA_SET_ELEM_EXPIRATION], + &expiration); + if (err) + return err; ++ ++ if (expiration > timeout) ++ return -ERANGE; + } + + if (nla[NFTA_SET_ELEM_EXPR]) { +@@ -6968,7 +6974,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, + if (err < 0) + goto err_parse_key_end; + +- if (timeout != READ_ONCE(set->timeout)) { ++ if (timeout != set->timeout) { + err = nft_set_ext_add(&tmpl, NFT_SET_EXT_TIMEOUT); + if (err < 0) + goto err_parse_key_end; +@@ -9131,7 +9137,7 @@ static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable) + flowtable->data.type->setup(&flowtable->data, hook->ops.dev, + FLOW_BLOCK_UNBIND); + list_del_rcu(&hook->list); +- kfree(hook); ++ kfree_rcu(hook, rcu); + } + kfree(flowtable->name); + module_put(flowtable->data.type->owner); +diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c +index d3d11dede54507..85450f60114263 100644 +--- a/net/netfilter/nft_compat.c ++++ b/net/netfilter/nft_compat.c +@@ -536,7 +536,7 @@ nft_match_large_init(const struct nft_ctx *ctx, const struct nft_expr *expr, + struct xt_match *m = expr->ops->data; + int ret; + +- priv->info = kmalloc(XT_ALIGN(m->matchsize), GFP_KERNEL); ++ priv->info = kmalloc(XT_ALIGN(m->matchsize), GFP_KERNEL_ACCOUNT); + if (!priv->info) + return -ENOMEM; + +@@ -810,7 +810,7 @@ nft_match_select_ops(const struct nft_ctx *ctx, + goto err; + } + +- ops = kzalloc(sizeof(struct nft_expr_ops), GFP_KERNEL); ++ ops = kzalloc(sizeof(struct nft_expr_ops), GFP_KERNEL_ACCOUNT); + if (!ops) { + err = -ENOMEM; + goto err; +@@ -900,7 +900,7 @@ nft_target_select_ops(const struct nft_ctx *ctx, + goto err; + } + +- ops = kzalloc(sizeof(struct nft_expr_ops), GFP_KERNEL); ++ ops = kzalloc(sizeof(struct nft_expr_ops), GFP_KERNEL_ACCOUNT); + if (!ops) { + err = -ENOMEM; + goto err; +diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c +index b4ada3ab21679b..489a9b34f1ecc1 100644 +--- a/net/netfilter/nft_dynset.c ++++ b/net/netfilter/nft_dynset.c +@@ -56,7 +56,7 @@ static struct nft_elem_priv *nft_dynset_new(struct nft_set *set, + if (!atomic_add_unless(&set->nelems, 1, set->size)) + return NULL; + +- timeout = priv->timeout ? : set->timeout; ++ timeout = priv->timeout ? : READ_ONCE(set->timeout); + elem_priv = nft_set_elem_init(set, &priv->tmpl, + ®s->data[priv->sreg_key], NULL, + ®s->data[priv->sreg_data], +@@ -95,7 +95,7 @@ void nft_dynset_eval(const struct nft_expr *expr, + expr, regs, &ext)) { + if (priv->op == NFT_DYNSET_OP_UPDATE && + nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION)) { +- timeout = priv->timeout ? : set->timeout; ++ timeout = priv->timeout ? : READ_ONCE(set->timeout); + *nft_set_ext_expiration(ext) = get_jiffies_64() + timeout; + } + +@@ -313,7 +313,7 @@ static int nft_dynset_init(const struct nft_ctx *ctx, + nft_dynset_ext_add_expr(priv); + + if (set->flags & NFT_SET_TIMEOUT) { +- if (timeout || set->timeout) { ++ if (timeout || READ_ONCE(set->timeout)) { + nft_set_ext_add(&priv->tmpl, NFT_SET_EXT_TIMEOUT); + nft_set_ext_add(&priv->tmpl, NFT_SET_EXT_EXPIRATION); + } +diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c +index 5defe6e4fd9820..e3558813799579 100644 +--- a/net/netfilter/nft_log.c ++++ b/net/netfilter/nft_log.c +@@ -163,7 +163,7 @@ static int nft_log_init(const struct nft_ctx *ctx, + + nla = tb[NFTA_LOG_PREFIX]; + if (nla != NULL) { +- priv->prefix = kmalloc(nla_len(nla) + 1, GFP_KERNEL); ++ priv->prefix = kmalloc(nla_len(nla) + 1, GFP_KERNEL_ACCOUNT); + if (priv->prefix == NULL) + return -ENOMEM; + nla_strscpy(priv->prefix, nla, nla_len(nla) + 1); +diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c +index 9139ce38ea7b9a..f23faf565b6873 100644 +--- a/net/netfilter/nft_meta.c ++++ b/net/netfilter/nft_meta.c +@@ -954,7 +954,7 @@ static int nft_secmark_obj_init(const struct nft_ctx *ctx, + if (tb[NFTA_SECMARK_CTX] == NULL) + return -EINVAL; + +- priv->ctx = nla_strdup(tb[NFTA_SECMARK_CTX], GFP_KERNEL); ++ priv->ctx = nla_strdup(tb[NFTA_SECMARK_CTX], GFP_KERNEL_ACCOUNT); + if (!priv->ctx) + return -ENOMEM; + +diff --git a/net/netfilter/nft_numgen.c b/net/netfilter/nft_numgen.c +index 7d29db7c2ac0f0..bd058babfc820c 100644 +--- a/net/netfilter/nft_numgen.c ++++ b/net/netfilter/nft_numgen.c +@@ -66,7 +66,7 @@ static int nft_ng_inc_init(const struct nft_ctx *ctx, + if (priv->offset + priv->modulus - 1 < priv->offset) + return -EOVERFLOW; + +- priv->counter = kmalloc(sizeof(*priv->counter), GFP_KERNEL); ++ priv->counter = kmalloc(sizeof(*priv->counter), GFP_KERNEL_ACCOUNT); + if (!priv->counter) + return -ENOMEM; + +diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c +index eb4c4a4ac7acea..7be342b495f5f7 100644 +--- a/net/netfilter/nft_set_pipapo.c ++++ b/net/netfilter/nft_set_pipapo.c +@@ -663,7 +663,7 @@ static int pipapo_realloc_mt(struct nft_pipapo_field *f, + check_add_overflow(rules, extra, &rules_alloc)) + return -EOVERFLOW; + +- new_mt = kvmalloc_array(rules_alloc, sizeof(*new_mt), GFP_KERNEL); ++ new_mt = kvmalloc_array(rules_alloc, sizeof(*new_mt), GFP_KERNEL_ACCOUNT); + if (!new_mt) + return -ENOMEM; + +@@ -936,7 +936,7 @@ static void pipapo_lt_bits_adjust(struct nft_pipapo_field *f) + return; + } + +- new_lt = kvzalloc(lt_size + NFT_PIPAPO_ALIGN_HEADROOM, GFP_KERNEL); ++ new_lt = kvzalloc(lt_size + NFT_PIPAPO_ALIGN_HEADROOM, GFP_KERNEL_ACCOUNT); + if (!new_lt) + return; + +@@ -1212,7 +1212,7 @@ static int pipapo_realloc_scratch(struct nft_pipapo_match *clone, + scratch = kzalloc_node(struct_size(scratch, map, + bsize_max * 2) + + NFT_PIPAPO_ALIGN_HEADROOM, +- GFP_KERNEL, cpu_to_node(i)); ++ GFP_KERNEL_ACCOUNT, cpu_to_node(i)); + if (!scratch) { + /* On failure, there's no need to undo previous + * allocations: this means that some scratch maps have +@@ -1427,7 +1427,7 @@ static struct nft_pipapo_match *pipapo_clone(struct nft_pipapo_match *old) + struct nft_pipapo_match *new; + int i; + +- new = kmalloc(struct_size(new, f, old->field_count), GFP_KERNEL); ++ new = kmalloc(struct_size(new, f, old->field_count), GFP_KERNEL_ACCOUNT); + if (!new) + return NULL; + +@@ -1457,7 +1457,7 @@ static struct nft_pipapo_match *pipapo_clone(struct nft_pipapo_match *old) + new_lt = kvzalloc(src->groups * NFT_PIPAPO_BUCKETS(src->bb) * + src->bsize * sizeof(*dst->lt) + + NFT_PIPAPO_ALIGN_HEADROOM, +- GFP_KERNEL); ++ GFP_KERNEL_ACCOUNT); + if (!new_lt) + goto out_lt; + +@@ -1470,7 +1470,8 @@ static struct nft_pipapo_match *pipapo_clone(struct nft_pipapo_match *old) + + if (src->rules > 0) { + dst->mt = kvmalloc_array(src->rules_alloc, +- sizeof(*src->mt), GFP_KERNEL); ++ sizeof(*src->mt), ++ GFP_KERNEL_ACCOUNT); + if (!dst->mt) + goto out_mt; + +diff --git a/net/netfilter/nft_tunnel.c b/net/netfilter/nft_tunnel.c +index 60a76e6e348e7b..5c6ed68cc6e058 100644 +--- a/net/netfilter/nft_tunnel.c ++++ b/net/netfilter/nft_tunnel.c +@@ -509,13 +509,14 @@ static int nft_tunnel_obj_init(const struct nft_ctx *ctx, + return err; + } + +- md = metadata_dst_alloc(priv->opts.len, METADATA_IP_TUNNEL, GFP_KERNEL); ++ md = metadata_dst_alloc(priv->opts.len, METADATA_IP_TUNNEL, ++ GFP_KERNEL_ACCOUNT); + if (!md) + return -ENOMEM; + + memcpy(&md->u.tun_info, &info, sizeof(info)); + #ifdef CONFIG_DST_CACHE +- err = dst_cache_init(&md->u.tun_info.dst_cache, GFP_KERNEL); ++ err = dst_cache_init(&md->u.tun_info.dst_cache, GFP_KERNEL_ACCOUNT); + if (err < 0) { + metadata_dst_free(md); + return err; +diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c +index 41ece61eb57ab7..00c51cf693f3d0 100644 +--- a/net/qrtr/af_qrtr.c ++++ b/net/qrtr/af_qrtr.c +@@ -884,7 +884,7 @@ static int qrtr_bcast_enqueue(struct qrtr_node *node, struct sk_buff *skb, + + mutex_lock(&qrtr_node_lock); + list_for_each_entry(node, &qrtr_all_nodes, item) { +- skbn = skb_clone(skb, GFP_KERNEL); ++ skbn = pskb_copy(skb, GFP_KERNEL); + if (!skbn) + break; + skb_set_owner_w(skbn, skb->sk); +diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c +index 593846d252143c..114fef65f92eab 100644 +--- a/net/tipc/bcast.c ++++ b/net/tipc/bcast.c +@@ -320,8 +320,8 @@ static int tipc_mcast_send_sync(struct net *net, struct sk_buff *skb, + { + struct tipc_msg *hdr, *_hdr; + struct sk_buff_head tmpq; ++ u16 cong_link_cnt = 0; + struct sk_buff *_skb; +- u16 cong_link_cnt; + int rc = 0; + + /* Is a cluster supporting with new capabilities ? */ +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 967bc4935b4ed9..e3bf14e489c5de 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -9658,7 +9658,8 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev, + return ERR_PTR(-ENOMEM); + + if (n_ssids) +- request->ssids = (void *)&request->channels[n_channels]; ++ request->ssids = (void *)request + ++ struct_size(request, channels, n_channels); + request->n_ssids = n_ssids; + if (ie_len) { + if (n_ssids) +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index 64c779788a6466..44c93b9a9751c1 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -3452,8 +3452,8 @@ int cfg80211_wext_siwscan(struct net_device *dev, + n_channels = ieee80211_get_num_supported_channels(wiphy); + } + +- creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) + +- n_channels * sizeof(void *), ++ creq = kzalloc(struct_size(creq, channels, n_channels) + ++ sizeof(struct cfg80211_ssid), + GFP_ATOMIC); + if (!creq) + return -ENOMEM; +@@ -3461,7 +3461,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, + creq->wiphy = wiphy; + creq->wdev = dev->ieee80211_ptr; + /* SSIDs come after channels */ +- creq->ssids = (void *)&creq->channels[n_channels]; ++ creq->ssids = (void *)creq + struct_size(creq, channels, n_channels); + creq->n_channels = n_channels; + creq->n_ssids = 1; + creq->scan_start = jiffies; +diff --git a/net/wireless/sme.c b/net/wireless/sme.c +index 1cfe673bc52f37..4b80af0edbe976 100644 +--- a/net/wireless/sme.c ++++ b/net/wireless/sme.c +@@ -115,7 +115,8 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev) + n_channels = i; + } + request->n_channels = n_channels; +- request->ssids = (void *)&request->channels[n_channels]; ++ request->ssids = (void *)request + ++ struct_size(request, channels, n_channels); + request->n_ssids = 1; + + memcpy(request->ssids[0].ssid, wdev->conn->params.ssid, +diff --git a/net/wireless/util.c b/net/wireless/util.c +index af6ec719567fc1..f1193aca79bae8 100644 +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -998,10 +998,10 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb, + * Diffserv Service Classes no update is needed: + * - Standard: DF + * - Low Priority Data: CS1 +- * - Multimedia Streaming: AF31, AF32, AF33 + * - Multimedia Conferencing: AF41, AF42, AF43 + * - Network Control Traffic: CS7 + * - Real-Time Interactive: CS4 ++ * - Signaling: CS5 + */ + switch (dscp >> 2) { + case 10: +@@ -1026,9 +1026,11 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb, + /* Broadcasting video: CS3 */ + ret = 4; + break; +- case 40: +- /* Signaling: CS5 */ +- ret = 5; ++ case 26: ++ case 28: ++ case 30: ++ /* Multimedia Streaming: AF31, AF32, AF33 */ ++ ret = 4; + break; + case 44: + /* Voice Admit: VA */ +diff --git a/net/xdp/xsk_buff_pool.c b/net/xdp/xsk_buff_pool.c +index c0e0204b963045..b0f24ebd05f0ba 100644 +--- a/net/xdp/xsk_buff_pool.c ++++ b/net/xdp/xsk_buff_pool.c +@@ -623,20 +623,31 @@ static u32 xp_alloc_reused(struct xsk_buff_pool *pool, struct xdp_buff **xdp, u3 + return nb_entries; + } + +-u32 xp_alloc_batch(struct xsk_buff_pool *pool, struct xdp_buff **xdp, u32 max) ++static u32 xp_alloc_slow(struct xsk_buff_pool *pool, struct xdp_buff **xdp, ++ u32 max) + { +- u32 nb_entries1 = 0, nb_entries2; ++ int i; + +- if (unlikely(pool->dev && dma_dev_need_sync(pool->dev))) { ++ for (i = 0; i < max; i++) { + struct xdp_buff *buff; + +- /* Slow path */ + buff = xp_alloc(pool); +- if (buff) +- *xdp = buff; +- return !!buff; ++ if (unlikely(!buff)) ++ return i; ++ *xdp = buff; ++ xdp++; + } + ++ return max; ++} ++ ++u32 xp_alloc_batch(struct xsk_buff_pool *pool, struct xdp_buff **xdp, u32 max) ++{ ++ u32 nb_entries1 = 0, nb_entries2; ++ ++ if (unlikely(pool->dev && dma_dev_need_sync(pool->dev))) ++ return xp_alloc_slow(pool, xdp, max); ++ + if (unlikely(pool->free_list_cnt)) { + nb_entries1 = xp_alloc_reused(pool, xdp, max); + if (nb_entries1 == max) +diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile +index 3e003dd6bea09c..dca56aa360ff32 100644 +--- a/samples/bpf/Makefile ++++ b/samples/bpf/Makefile +@@ -169,6 +169,10 @@ BPF_EXTRA_CFLAGS += -I$(srctree)/arch/mips/include/asm/mach-generic + endif + endif + ++ifeq ($(ARCH), x86) ++BPF_EXTRA_CFLAGS += -fcf-protection ++endif ++ + TPROGS_CFLAGS += -Wall -O2 + TPROGS_CFLAGS += -Wmissing-prototypes + TPROGS_CFLAGS += -Wstrict-prototypes +@@ -405,7 +409,7 @@ $(obj)/%.o: $(src)/%.c + -Wno-gnu-variable-sized-type-not-at-end \ + -Wno-address-of-packed-member -Wno-tautological-compare \ + -Wno-unknown-warning-option $(CLANG_ARCH_ARGS) \ +- -fno-asynchronous-unwind-tables -fcf-protection \ ++ -fno-asynchronous-unwind-tables \ + -I$(srctree)/samples/bpf/ -include asm_goto_workaround.h \ + -O2 -emit-llvm -Xclang -disable-llvm-passes -c $< -o - | \ + $(OPT) -O2 -mtriple=bpf-pc-linux | $(LLVM_DIS) | \ +diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h +index 67bf888c3bd6b9..c42ed8a73f1cef 100644 +--- a/security/apparmor/include/net.h ++++ b/security/apparmor/include/net.h +@@ -51,10 +51,9 @@ struct aa_sk_ctx { + struct aa_label *peer; + }; + +-#define SK_CTX(X) ((X)->sk_security) + static inline struct aa_sk_ctx *aa_sock(const struct sock *sk) + { +- return sk->sk_security; ++ return sk->sk_security + apparmor_blob_sizes.lbs_sock; + } + + #define DEFINE_AUDIT_NET(NAME, OP, SK, F, T, P) \ +diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c +index 4373b914acf204..b8366fca98d23e 100644 +--- a/security/apparmor/lsm.c ++++ b/security/apparmor/lsm.c +@@ -1057,27 +1057,12 @@ static int apparmor_userns_create(const struct cred *cred) + return error; + } + +-static int apparmor_sk_alloc_security(struct sock *sk, int family, gfp_t flags) +-{ +- struct aa_sk_ctx *ctx; +- +- ctx = kzalloc(sizeof(*ctx), flags); +- if (!ctx) +- return -ENOMEM; +- +- sk->sk_security = ctx; +- +- return 0; +-} +- + static void apparmor_sk_free_security(struct sock *sk) + { + struct aa_sk_ctx *ctx = aa_sock(sk); + +- sk->sk_security = NULL; + aa_put_label(ctx->label); + aa_put_label(ctx->peer); +- kfree(ctx); + } + + /** +@@ -1432,6 +1417,7 @@ struct lsm_blob_sizes apparmor_blob_sizes __ro_after_init = { + .lbs_cred = sizeof(struct aa_label *), + .lbs_file = sizeof(struct aa_file_ctx), + .lbs_task = sizeof(struct aa_task_ctx), ++ .lbs_sock = sizeof(struct aa_sk_ctx), + }; + + static const struct lsm_id apparmor_lsmid = { +@@ -1477,7 +1463,6 @@ static struct security_hook_list apparmor_hooks[] __ro_after_init = { + LSM_HOOK_INIT(getprocattr, apparmor_getprocattr), + LSM_HOOK_INIT(setprocattr, apparmor_setprocattr), + +- LSM_HOOK_INIT(sk_alloc_security, apparmor_sk_alloc_security), + LSM_HOOK_INIT(sk_free_security, apparmor_sk_free_security), + LSM_HOOK_INIT(sk_clone_security, apparmor_sk_clone_security), + +diff --git a/security/apparmor/net.c b/security/apparmor/net.c +index 87e934b2b54887..77413a5191179a 100644 +--- a/security/apparmor/net.c ++++ b/security/apparmor/net.c +@@ -151,7 +151,7 @@ static int aa_label_sk_perm(const struct cred *subj_cred, + const char *op, u32 request, + struct sock *sk) + { +- struct aa_sk_ctx *ctx = SK_CTX(sk); ++ struct aa_sk_ctx *ctx = aa_sock(sk); + int error = 0; + + AA_BUG(!label); +diff --git a/security/bpf/hooks.c b/security/bpf/hooks.c +index 57b9ffd53c98ae..3663aec7bcbd21 100644 +--- a/security/bpf/hooks.c ++++ b/security/bpf/hooks.c +@@ -31,7 +31,6 @@ static int __init bpf_lsm_init(void) + + struct lsm_blob_sizes bpf_lsm_blob_sizes __ro_after_init = { + .lbs_inode = sizeof(struct bpf_storage_blob), +- .lbs_task = sizeof(struct bpf_storage_blob), + }; + + DEFINE_LSM(bpf) = { +diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h +index c51e24d24d1e9e..3c323ca213d42c 100644 +--- a/security/integrity/ima/ima.h ++++ b/security/integrity/ima/ima.h +@@ -223,7 +223,7 @@ static inline void ima_inode_set_iint(const struct inode *inode, + + struct ima_iint_cache *ima_iint_find(struct inode *inode); + struct ima_iint_cache *ima_inode_get(struct inode *inode); +-void ima_inode_free(struct inode *inode); ++void ima_inode_free_rcu(void *inode_security); + void __init ima_iintcache_init(void); + + extern const int read_idmap[]; +diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c +index e23412a2c56b09..00b249101f98d3 100644 +--- a/security/integrity/ima/ima_iint.c ++++ b/security/integrity/ima/ima_iint.c +@@ -109,22 +109,18 @@ struct ima_iint_cache *ima_inode_get(struct inode *inode) + } + + /** +- * ima_inode_free - Called on inode free +- * @inode: Pointer to the inode ++ * ima_inode_free_rcu - Called to free an inode via a RCU callback ++ * @inode_security: The inode->i_security pointer + * +- * Free the iint associated with an inode. ++ * Free the IMA data associated with an inode. + */ +-void ima_inode_free(struct inode *inode) ++void ima_inode_free_rcu(void *inode_security) + { +- struct ima_iint_cache *iint; +- +- if (!IS_IMA(inode)) +- return; +- +- iint = ima_iint_find(inode); +- ima_inode_set_iint(inode, NULL); ++ struct ima_iint_cache **iint_p = inode_security + ima_blob_sizes.lbs_inode; + +- ima_iint_free(iint); ++ /* *iint_p should be NULL if !IS_IMA(inode) */ ++ if (*iint_p) ++ ima_iint_free(*iint_p); + } + + static void ima_iint_init_once(void *foo) +diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c +index f04f43af651c8e..5b3394864b218e 100644 +--- a/security/integrity/ima/ima_main.c ++++ b/security/integrity/ima/ima_main.c +@@ -1193,7 +1193,7 @@ static struct security_hook_list ima_hooks[] __ro_after_init = { + #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS + LSM_HOOK_INIT(kernel_module_request, ima_kernel_module_request), + #endif +- LSM_HOOK_INIT(inode_free_security, ima_inode_free), ++ LSM_HOOK_INIT(inode_free_security_rcu, ima_inode_free_rcu), + }; + + static const struct lsm_id ima_lsmid = { +diff --git a/security/landlock/fs.c b/security/landlock/fs.c +index 7877a64cc6b87c..0804f76a67be2e 100644 +--- a/security/landlock/fs.c ++++ b/security/landlock/fs.c +@@ -1207,13 +1207,16 @@ static int current_check_refer_path(struct dentry *const old_dentry, + + /* Inode hooks */ + +-static void hook_inode_free_security(struct inode *const inode) ++static void hook_inode_free_security_rcu(void *inode_security) + { ++ struct landlock_inode_security *inode_sec; ++ + /* + * All inodes must already have been untied from their object by + * release_inode() or hook_sb_delete(). + */ +- WARN_ON_ONCE(landlock_inode(inode)->object); ++ inode_sec = inode_security + landlock_blob_sizes.lbs_inode; ++ WARN_ON_ONCE(inode_sec->object); + } + + /* Super-block hooks */ +@@ -1637,7 +1640,7 @@ static int hook_file_ioctl_compat(struct file *file, unsigned int cmd, + } + + static struct security_hook_list landlock_hooks[] __ro_after_init = { +- LSM_HOOK_INIT(inode_free_security, hook_inode_free_security), ++ LSM_HOOK_INIT(inode_free_security_rcu, hook_inode_free_security_rcu), + + LSM_HOOK_INIT(sb_delete, hook_sb_delete), + LSM_HOOK_INIT(sb_mount, hook_sb_mount), +diff --git a/security/security.c b/security/security.c +index 8cee5b6c6e6d53..43166e341526c0 100644 +--- a/security/security.c ++++ b/security/security.c +@@ -29,6 +29,7 @@ + #include <linux/msg.h> + #include <linux/overflow.h> + #include <net/flow.h> ++#include <net/sock.h> + + /* How many LSMs were built into the kernel? */ + #define LSM_COUNT (__end_lsm_info - __start_lsm_info) +@@ -227,6 +228,7 @@ static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed) + lsm_set_blob_size(&needed->lbs_inode, &blob_sizes.lbs_inode); + lsm_set_blob_size(&needed->lbs_ipc, &blob_sizes.lbs_ipc); + lsm_set_blob_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg); ++ lsm_set_blob_size(&needed->lbs_sock, &blob_sizes.lbs_sock); + lsm_set_blob_size(&needed->lbs_superblock, &blob_sizes.lbs_superblock); + lsm_set_blob_size(&needed->lbs_task, &blob_sizes.lbs_task); + lsm_set_blob_size(&needed->lbs_xattr_count, +@@ -401,6 +403,7 @@ static void __init ordered_lsm_init(void) + init_debug("inode blob size = %d\n", blob_sizes.lbs_inode); + init_debug("ipc blob size = %d\n", blob_sizes.lbs_ipc); + init_debug("msg_msg blob size = %d\n", blob_sizes.lbs_msg_msg); ++ init_debug("sock blob size = %d\n", blob_sizes.lbs_sock); + init_debug("superblock blob size = %d\n", blob_sizes.lbs_superblock); + init_debug("task blob size = %d\n", blob_sizes.lbs_task); + init_debug("xattr slots = %d\n", blob_sizes.lbs_xattr_count); +@@ -1596,9 +1599,8 @@ int security_inode_alloc(struct inode *inode) + + static void inode_free_by_rcu(struct rcu_head *head) + { +- /* +- * The rcu head is at the start of the inode blob +- */ ++ /* The rcu head is at the start of the inode blob */ ++ call_void_hook(inode_free_security_rcu, head); + kmem_cache_free(lsm_inode_cache, head); + } + +@@ -1606,23 +1608,24 @@ static void inode_free_by_rcu(struct rcu_head *head) + * security_inode_free() - Free an inode's LSM blob + * @inode: the inode + * +- * Deallocate the inode security structure and set @inode->i_security to NULL. ++ * Release any LSM resources associated with @inode, although due to the ++ * inode's RCU protections it is possible that the resources will not be ++ * fully released until after the current RCU grace period has elapsed. ++ * ++ * It is important for LSMs to note that despite being present in a call to ++ * security_inode_free(), @inode may still be referenced in a VFS path walk ++ * and calls to security_inode_permission() may be made during, or after, ++ * a call to security_inode_free(). For this reason the inode->i_security ++ * field is released via a call_rcu() callback and any LSMs which need to ++ * retain inode state for use in security_inode_permission() should only ++ * release that state in the inode_free_security_rcu() LSM hook callback. + */ + void security_inode_free(struct inode *inode) + { + call_void_hook(inode_free_security, inode); +- /* +- * The inode may still be referenced in a path walk and +- * a call to security_inode_permission() can be made +- * after inode_free_security() is called. Ideally, the VFS +- * wouldn't do this, but fixing that is a much harder +- * job. For now, simply free the i_security via RCU, and +- * leave the current inode->i_security pointer intact. +- * The inode will be freed after the RCU grace period too. +- */ +- if (inode->i_security) +- call_rcu((struct rcu_head *)inode->i_security, +- inode_free_by_rcu); ++ if (!inode->i_security) ++ return; ++ call_rcu((struct rcu_head *)inode->i_security, inode_free_by_rcu); + } + + /** +@@ -4673,6 +4676,28 @@ int security_socket_getpeersec_dgram(struct socket *sock, + } + EXPORT_SYMBOL(security_socket_getpeersec_dgram); + ++/** ++ * lsm_sock_alloc - allocate a composite sock blob ++ * @sock: the sock that needs a blob ++ * @priority: allocation mode ++ * ++ * Allocate the sock blob for all the modules ++ * ++ * Returns 0, or -ENOMEM if memory can't be allocated. ++ */ ++static int lsm_sock_alloc(struct sock *sock, gfp_t priority) ++{ ++ if (blob_sizes.lbs_sock == 0) { ++ sock->sk_security = NULL; ++ return 0; ++ } ++ ++ sock->sk_security = kzalloc(blob_sizes.lbs_sock, priority); ++ if (sock->sk_security == NULL) ++ return -ENOMEM; ++ return 0; ++} ++ + /** + * security_sk_alloc() - Allocate and initialize a sock's LSM blob + * @sk: sock +@@ -4686,7 +4711,14 @@ EXPORT_SYMBOL(security_socket_getpeersec_dgram); + */ + int security_sk_alloc(struct sock *sk, int family, gfp_t priority) + { +- return call_int_hook(sk_alloc_security, sk, family, priority); ++ int rc = lsm_sock_alloc(sk, priority); ++ ++ if (unlikely(rc)) ++ return rc; ++ rc = call_int_hook(sk_alloc_security, sk, family, priority); ++ if (unlikely(rc)) ++ security_sk_free(sk); ++ return rc; + } + + /** +@@ -4698,6 +4730,8 @@ int security_sk_alloc(struct sock *sk, int family, gfp_t priority) + void security_sk_free(struct sock *sk) + { + call_void_hook(sk_free_security, sk); ++ kfree(sk->sk_security); ++ sk->sk_security = NULL; + } + + /** +diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c +index 400eca4ad0fb6c..c11303d662d809 100644 +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -4594,7 +4594,7 @@ static int socket_sockcreate_sid(const struct task_security_struct *tsec, + + static int sock_has_perm(struct sock *sk, u32 perms) + { +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); + struct common_audit_data ad; + struct lsm_network_audit net; + +@@ -4662,7 +4662,7 @@ static int selinux_socket_post_create(struct socket *sock, int family, + isec->initialized = LABEL_INITIALIZED; + + if (sock->sk) { +- sksec = sock->sk->sk_security; ++ sksec = selinux_sock(sock->sk); + sksec->sclass = sclass; + sksec->sid = sid; + /* Allows detection of the first association on this socket */ +@@ -4678,8 +4678,8 @@ static int selinux_socket_post_create(struct socket *sock, int family, + static int selinux_socket_socketpair(struct socket *socka, + struct socket *sockb) + { +- struct sk_security_struct *sksec_a = socka->sk->sk_security; +- struct sk_security_struct *sksec_b = sockb->sk->sk_security; ++ struct sk_security_struct *sksec_a = selinux_sock(socka->sk); ++ struct sk_security_struct *sksec_b = selinux_sock(sockb->sk); + + sksec_a->peer_sid = sksec_b->sid; + sksec_b->peer_sid = sksec_a->sid; +@@ -4694,7 +4694,7 @@ static int selinux_socket_socketpair(struct socket *socka, + static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) + { + struct sock *sk = sock->sk; +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); + u16 family; + int err; + +@@ -4834,7 +4834,7 @@ static int selinux_socket_connect_helper(struct socket *sock, + struct sockaddr *address, int addrlen) + { + struct sock *sk = sock->sk; +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); + int err; + + err = sock_has_perm(sk, SOCKET__CONNECT); +@@ -5012,9 +5012,9 @@ static int selinux_socket_unix_stream_connect(struct sock *sock, + struct sock *other, + struct sock *newsk) + { +- struct sk_security_struct *sksec_sock = sock->sk_security; +- struct sk_security_struct *sksec_other = other->sk_security; +- struct sk_security_struct *sksec_new = newsk->sk_security; ++ struct sk_security_struct *sksec_sock = selinux_sock(sock); ++ struct sk_security_struct *sksec_other = selinux_sock(other); ++ struct sk_security_struct *sksec_new = selinux_sock(newsk); + struct common_audit_data ad; + struct lsm_network_audit net; + int err; +@@ -5043,8 +5043,8 @@ static int selinux_socket_unix_stream_connect(struct sock *sock, + static int selinux_socket_unix_may_send(struct socket *sock, + struct socket *other) + { +- struct sk_security_struct *ssec = sock->sk->sk_security; +- struct sk_security_struct *osec = other->sk->sk_security; ++ struct sk_security_struct *ssec = selinux_sock(sock->sk); ++ struct sk_security_struct *osec = selinux_sock(other->sk); + struct common_audit_data ad; + struct lsm_network_audit net; + +@@ -5081,7 +5081,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, + u16 family) + { + int err = 0; +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); + u32 sk_sid = sksec->sid; + struct common_audit_data ad; + struct lsm_network_audit net; +@@ -5110,7 +5110,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, + static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) + { + int err, peerlbl_active, secmark_active; +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); + u16 family = sk->sk_family; + u32 sk_sid = sksec->sid; + struct common_audit_data ad; +@@ -5178,7 +5178,7 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, + int err = 0; + char *scontext = NULL; + u32 scontext_len; +- struct sk_security_struct *sksec = sock->sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sock->sk); + u32 peer_sid = SECSID_NULL; + + if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET || +@@ -5238,34 +5238,27 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, + + static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) + { +- struct sk_security_struct *sksec; +- +- sksec = kzalloc(sizeof(*sksec), priority); +- if (!sksec) +- return -ENOMEM; ++ struct sk_security_struct *sksec = selinux_sock(sk); + + sksec->peer_sid = SECINITSID_UNLABELED; + sksec->sid = SECINITSID_UNLABELED; + sksec->sclass = SECCLASS_SOCKET; + selinux_netlbl_sk_security_reset(sksec); +- sk->sk_security = sksec; + + return 0; + } + + static void selinux_sk_free_security(struct sock *sk) + { +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); + +- sk->sk_security = NULL; + selinux_netlbl_sk_security_free(sksec); +- kfree(sksec); + } + + static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) + { +- struct sk_security_struct *sksec = sk->sk_security; +- struct sk_security_struct *newsksec = newsk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); ++ struct sk_security_struct *newsksec = selinux_sock(newsk); + + newsksec->sid = sksec->sid; + newsksec->peer_sid = sksec->peer_sid; +@@ -5279,7 +5272,7 @@ static void selinux_sk_getsecid(const struct sock *sk, u32 *secid) + if (!sk) + *secid = SECINITSID_ANY_SOCKET; + else { +- const struct sk_security_struct *sksec = sk->sk_security; ++ const struct sk_security_struct *sksec = selinux_sock(sk); + + *secid = sksec->sid; + } +@@ -5289,7 +5282,7 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent) + { + struct inode_security_struct *isec = + inode_security_novalidate(SOCK_INODE(parent)); +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); + + if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 || + sk->sk_family == PF_UNIX) +@@ -5306,7 +5299,7 @@ static int selinux_sctp_process_new_assoc(struct sctp_association *asoc, + { + struct sock *sk = asoc->base.sk; + u16 family = sk->sk_family; +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); + struct common_audit_data ad; + struct lsm_network_audit net; + int err; +@@ -5361,7 +5354,7 @@ static int selinux_sctp_process_new_assoc(struct sctp_association *asoc, + static int selinux_sctp_assoc_request(struct sctp_association *asoc, + struct sk_buff *skb) + { +- struct sk_security_struct *sksec = asoc->base.sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(asoc->base.sk); + u32 conn_sid; + int err; + +@@ -5394,7 +5387,7 @@ static int selinux_sctp_assoc_request(struct sctp_association *asoc, + static int selinux_sctp_assoc_established(struct sctp_association *asoc, + struct sk_buff *skb) + { +- struct sk_security_struct *sksec = asoc->base.sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(asoc->base.sk); + + if (!selinux_policycap_extsockclass()) + return 0; +@@ -5493,8 +5486,8 @@ static int selinux_sctp_bind_connect(struct sock *sk, int optname, + static void selinux_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk, + struct sock *newsk) + { +- struct sk_security_struct *sksec = sk->sk_security; +- struct sk_security_struct *newsksec = newsk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); ++ struct sk_security_struct *newsksec = selinux_sock(newsk); + + /* If policy does not support SECCLASS_SCTP_SOCKET then call + * the non-sctp clone version. +@@ -5510,8 +5503,8 @@ static void selinux_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk + + static int selinux_mptcp_add_subflow(struct sock *sk, struct sock *ssk) + { +- struct sk_security_struct *ssksec = ssk->sk_security; +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *ssksec = selinux_sock(ssk); ++ struct sk_security_struct *sksec = selinux_sock(sk); + + ssksec->sclass = sksec->sclass; + ssksec->sid = sksec->sid; +@@ -5526,7 +5519,7 @@ static int selinux_mptcp_add_subflow(struct sock *sk, struct sock *ssk) + static int selinux_inet_conn_request(const struct sock *sk, struct sk_buff *skb, + struct request_sock *req) + { +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); + int err; + u16 family = req->rsk_ops->family; + u32 connsid; +@@ -5547,7 +5540,7 @@ static int selinux_inet_conn_request(const struct sock *sk, struct sk_buff *skb, + static void selinux_inet_csk_clone(struct sock *newsk, + const struct request_sock *req) + { +- struct sk_security_struct *newsksec = newsk->sk_security; ++ struct sk_security_struct *newsksec = selinux_sock(newsk); + + newsksec->sid = req->secid; + newsksec->peer_sid = req->peer_secid; +@@ -5564,7 +5557,7 @@ static void selinux_inet_csk_clone(struct sock *newsk, + static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) + { + u16 family = sk->sk_family; +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); + + /* handle mapped IPv4 packets arriving via IPv6 sockets */ + if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) +@@ -5639,7 +5632,7 @@ static int selinux_tun_dev_attach_queue(void *security) + static int selinux_tun_dev_attach(struct sock *sk, void *security) + { + struct tun_security_struct *tunsec = security; +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); + + /* we don't currently perform any NetLabel based labeling here and it + * isn't clear that we would want to do so anyway; while we could apply +@@ -5762,7 +5755,7 @@ static unsigned int selinux_ip_output(void *priv, struct sk_buff *skb, + return NF_ACCEPT; + + /* standard practice, label using the parent socket */ +- sksec = sk->sk_security; ++ sksec = selinux_sock(sk); + sid = sksec->sid; + } else + sid = SECINITSID_KERNEL; +@@ -5785,7 +5778,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, + sk = skb_to_full_sk(skb); + if (sk == NULL) + return NF_ACCEPT; +- sksec = sk->sk_security; ++ sksec = selinux_sock(sk); + + ad_net_init_from_iif(&ad, &net, state->out->ifindex, state->pf); + if (selinux_parse_skb(skb, &ad, NULL, 0, &proto)) +@@ -5874,7 +5867,7 @@ static unsigned int selinux_ip_postroute(void *priv, + u32 skb_sid; + struct sk_security_struct *sksec; + +- sksec = sk->sk_security; ++ sksec = selinux_sock(sk); + if (selinux_skb_peerlbl_sid(skb, family, &skb_sid)) + return NF_DROP; + /* At this point, if the returned skb peerlbl is SECSID_NULL +@@ -5903,7 +5896,7 @@ static unsigned int selinux_ip_postroute(void *priv, + } else { + /* Locally generated packet, fetch the security label from the + * associated socket. */ +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); + peer_sid = sksec->sid; + secmark_perm = PACKET__SEND; + } +@@ -5946,7 +5939,7 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) + unsigned int data_len = skb->len; + unsigned char *data = skb->data; + struct nlmsghdr *nlh; +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); + u16 sclass = sksec->sclass; + u32 perm; + +@@ -7004,6 +6997,7 @@ struct lsm_blob_sizes selinux_blob_sizes __ro_after_init = { + .lbs_inode = sizeof(struct inode_security_struct), + .lbs_ipc = sizeof(struct ipc_security_struct), + .lbs_msg_msg = sizeof(struct msg_security_struct), ++ .lbs_sock = sizeof(struct sk_security_struct), + .lbs_superblock = sizeof(struct superblock_security_struct), + .lbs_xattr_count = SELINUX_INODE_INIT_XATTRS, + }; +diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h +index dea1d6f3ed2d3b..b074099acbaf79 100644 +--- a/security/selinux/include/objsec.h ++++ b/security/selinux/include/objsec.h +@@ -195,4 +195,9 @@ selinux_superblock(const struct super_block *superblock) + return superblock->s_security + selinux_blob_sizes.lbs_superblock; + } + ++static inline struct sk_security_struct *selinux_sock(const struct sock *sock) ++{ ++ return sock->sk_security + selinux_blob_sizes.lbs_sock; ++} ++ + #endif /* _SELINUX_OBJSEC_H_ */ +diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c +index 55885634e8804a..fbe5f8c29f8137 100644 +--- a/security/selinux/netlabel.c ++++ b/security/selinux/netlabel.c +@@ -17,6 +17,7 @@ + #include <linux/gfp.h> + #include <linux/ip.h> + #include <linux/ipv6.h> ++#include <linux/lsm_hooks.h> + #include <net/sock.h> + #include <net/netlabel.h> + #include <net/ip.h> +@@ -68,7 +69,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb, + static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk) + { + int rc; +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); + struct netlbl_lsm_secattr *secattr; + + if (sksec->nlbl_secattr != NULL) +@@ -100,7 +101,7 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_getattr( + const struct sock *sk, + u32 sid) + { +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); + struct netlbl_lsm_secattr *secattr = sksec->nlbl_secattr; + + if (secattr == NULL) +@@ -240,7 +241,7 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, + * being labeled by it's parent socket, if it is just exit */ + sk = skb_to_full_sk(skb); + if (sk != NULL) { +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); + + if (sksec->nlbl_state != NLBL_REQSKB) + return 0; +@@ -277,7 +278,7 @@ int selinux_netlbl_sctp_assoc_request(struct sctp_association *asoc, + { + int rc; + struct netlbl_lsm_secattr secattr; +- struct sk_security_struct *sksec = asoc->base.sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(asoc->base.sk); + struct sockaddr_in addr4; + struct sockaddr_in6 addr6; + +@@ -356,7 +357,7 @@ int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family) + */ + void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family) + { +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); + + if (family == PF_INET) + sksec->nlbl_state = NLBL_LABELED; +@@ -374,8 +375,8 @@ void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family) + */ + void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk) + { +- struct sk_security_struct *sksec = sk->sk_security; +- struct sk_security_struct *newsksec = newsk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); ++ struct sk_security_struct *newsksec = selinux_sock(newsk); + + newsksec->nlbl_state = sksec->nlbl_state; + } +@@ -393,7 +394,7 @@ void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk) + int selinux_netlbl_socket_post_create(struct sock *sk, u16 family) + { + int rc; +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); + struct netlbl_lsm_secattr *secattr; + + if (family != PF_INET && family != PF_INET6) +@@ -510,7 +511,7 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, + { + int rc = 0; + struct sock *sk = sock->sk; +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); + struct netlbl_lsm_secattr secattr; + + if (selinux_netlbl_option(level, optname) && +@@ -548,7 +549,7 @@ static int selinux_netlbl_socket_connect_helper(struct sock *sk, + struct sockaddr *addr) + { + int rc; +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); + struct netlbl_lsm_secattr *secattr; + + /* connected sockets are allowed to disconnect when the address family +@@ -587,7 +588,7 @@ static int selinux_netlbl_socket_connect_helper(struct sock *sk, + int selinux_netlbl_socket_connect_locked(struct sock *sk, + struct sockaddr *addr) + { +- struct sk_security_struct *sksec = sk->sk_security; ++ struct sk_security_struct *sksec = selinux_sock(sk); + + if (sksec->nlbl_state != NLBL_REQSKB && + sksec->nlbl_state != NLBL_CONNLABELED) +diff --git a/security/smack/smack.h b/security/smack/smack.h +index 041688e5a77a3e..297f21446f4568 100644 +--- a/security/smack/smack.h ++++ b/security/smack/smack.h +@@ -355,6 +355,11 @@ static inline struct superblock_smack *smack_superblock( + return superblock->s_security + smack_blob_sizes.lbs_superblock; + } + ++static inline struct socket_smack *smack_sock(const struct sock *sock) ++{ ++ return sock->sk_security + smack_blob_sizes.lbs_sock; ++} ++ + /* + * Is the directory transmuting? + */ +diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c +index 002a1b9ed83a56..6ec9a40f3ec592 100644 +--- a/security/smack/smack_lsm.c ++++ b/security/smack/smack_lsm.c +@@ -1606,7 +1606,7 @@ static int smack_inode_getsecurity(struct mnt_idmap *idmap, + if (sock == NULL || sock->sk == NULL) + return -EOPNOTSUPP; + +- ssp = sock->sk->sk_security; ++ ssp = smack_sock(sock->sk); + + if (strcmp(name, XATTR_SMACK_IPIN) == 0) + isp = ssp->smk_in; +@@ -1994,7 +1994,7 @@ static int smack_file_receive(struct file *file) + + if (inode->i_sb->s_magic == SOCKFS_MAGIC) { + sock = SOCKET_I(inode); +- ssp = sock->sk->sk_security; ++ ssp = smack_sock(sock->sk); + tsp = smack_cred(current_cred()); + /* + * If the receiving process can't write to the +@@ -2409,11 +2409,7 @@ static void smack_task_to_inode(struct task_struct *p, struct inode *inode) + static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) + { + struct smack_known *skp = smk_of_current(); +- struct socket_smack *ssp; +- +- ssp = kzalloc(sizeof(struct socket_smack), gfp_flags); +- if (ssp == NULL) +- return -ENOMEM; ++ struct socket_smack *ssp = smack_sock(sk); + + /* + * Sockets created by kernel threads receive web label. +@@ -2427,11 +2423,10 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) + } + ssp->smk_packet = NULL; + +- sk->sk_security = ssp; +- + return 0; + } + ++#ifdef SMACK_IPV6_PORT_LABELING + /** + * smack_sk_free_security - Free a socket blob + * @sk: the socket +@@ -2440,7 +2435,6 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) + */ + static void smack_sk_free_security(struct sock *sk) + { +-#ifdef SMACK_IPV6_PORT_LABELING + struct smk_port_label *spp; + + if (sk->sk_family == PF_INET6) { +@@ -2453,9 +2447,8 @@ static void smack_sk_free_security(struct sock *sk) + } + rcu_read_unlock(); + } +-#endif +- kfree(sk->sk_security); + } ++#endif + + /** + * smack_sk_clone_security - Copy security context +@@ -2466,8 +2459,8 @@ static void smack_sk_free_security(struct sock *sk) + */ + static void smack_sk_clone_security(const struct sock *sk, struct sock *newsk) + { +- struct socket_smack *ssp_old = sk->sk_security; +- struct socket_smack *ssp_new = newsk->sk_security; ++ struct socket_smack *ssp_old = smack_sock(sk); ++ struct socket_smack *ssp_new = smack_sock(newsk); + + *ssp_new = *ssp_old; + } +@@ -2583,7 +2576,7 @@ static struct smack_known *smack_ipv6host_label(struct sockaddr_in6 *sip) + */ + static int smack_netlbl_add(struct sock *sk) + { +- struct socket_smack *ssp = sk->sk_security; ++ struct socket_smack *ssp = smack_sock(sk); + struct smack_known *skp = ssp->smk_out; + int rc; + +@@ -2616,7 +2609,7 @@ static int smack_netlbl_add(struct sock *sk) + */ + static void smack_netlbl_delete(struct sock *sk) + { +- struct socket_smack *ssp = sk->sk_security; ++ struct socket_smack *ssp = smack_sock(sk); + + /* + * Take the label off the socket if one is set. +@@ -2648,7 +2641,7 @@ static int smk_ipv4_check(struct sock *sk, struct sockaddr_in *sap) + struct smack_known *skp; + int rc = 0; + struct smack_known *hkp; +- struct socket_smack *ssp = sk->sk_security; ++ struct socket_smack *ssp = smack_sock(sk); + struct smk_audit_info ad; + + rcu_read_lock(); +@@ -2721,7 +2714,7 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address) + { + struct sock *sk = sock->sk; + struct sockaddr_in6 *addr6; +- struct socket_smack *ssp = sock->sk->sk_security; ++ struct socket_smack *ssp = smack_sock(sock->sk); + struct smk_port_label *spp; + unsigned short port = 0; + +@@ -2809,7 +2802,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address, + int act) + { + struct smk_port_label *spp; +- struct socket_smack *ssp = sk->sk_security; ++ struct socket_smack *ssp = smack_sock(sk); + struct smack_known *skp = NULL; + unsigned short port; + struct smack_known *object; +@@ -2912,7 +2905,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, + if (sock == NULL || sock->sk == NULL) + return -EOPNOTSUPP; + +- ssp = sock->sk->sk_security; ++ ssp = smack_sock(sock->sk); + + if (strcmp(name, XATTR_SMACK_IPIN) == 0) + ssp->smk_in = skp; +@@ -2960,7 +2953,7 @@ static int smack_socket_post_create(struct socket *sock, int family, + * Sockets created by kernel threads receive web label. + */ + if (unlikely(current->flags & PF_KTHREAD)) { +- ssp = sock->sk->sk_security; ++ ssp = smack_sock(sock->sk); + ssp->smk_in = &smack_known_web; + ssp->smk_out = &smack_known_web; + } +@@ -2985,8 +2978,8 @@ static int smack_socket_post_create(struct socket *sock, int family, + static int smack_socket_socketpair(struct socket *socka, + struct socket *sockb) + { +- struct socket_smack *asp = socka->sk->sk_security; +- struct socket_smack *bsp = sockb->sk->sk_security; ++ struct socket_smack *asp = smack_sock(socka->sk); ++ struct socket_smack *bsp = smack_sock(sockb->sk); + + asp->smk_packet = bsp->smk_out; + bsp->smk_packet = asp->smk_out; +@@ -3049,7 +3042,7 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap, + if (__is_defined(SMACK_IPV6_SECMARK_LABELING)) + rsp = smack_ipv6host_label(sip); + if (rsp != NULL) { +- struct socket_smack *ssp = sock->sk->sk_security; ++ struct socket_smack *ssp = smack_sock(sock->sk); + + rc = smk_ipv6_check(ssp->smk_out, rsp, sip, + SMK_CONNECTING); +@@ -3844,9 +3837,9 @@ static int smack_unix_stream_connect(struct sock *sock, + { + struct smack_known *skp; + struct smack_known *okp; +- struct socket_smack *ssp = sock->sk_security; +- struct socket_smack *osp = other->sk_security; +- struct socket_smack *nsp = newsk->sk_security; ++ struct socket_smack *ssp = smack_sock(sock); ++ struct socket_smack *osp = smack_sock(other); ++ struct socket_smack *nsp = smack_sock(newsk); + struct smk_audit_info ad; + int rc = 0; + #ifdef CONFIG_AUDIT +@@ -3898,8 +3891,8 @@ static int smack_unix_stream_connect(struct sock *sock, + */ + static int smack_unix_may_send(struct socket *sock, struct socket *other) + { +- struct socket_smack *ssp = sock->sk->sk_security; +- struct socket_smack *osp = other->sk->sk_security; ++ struct socket_smack *ssp = smack_sock(sock->sk); ++ struct socket_smack *osp = smack_sock(other->sk); + struct smk_audit_info ad; + int rc; + +@@ -3936,7 +3929,7 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, + struct sockaddr_in6 *sap = (struct sockaddr_in6 *) msg->msg_name; + #endif + #ifdef SMACK_IPV6_SECMARK_LABELING +- struct socket_smack *ssp = sock->sk->sk_security; ++ struct socket_smack *ssp = smack_sock(sock->sk); + struct smack_known *rsp; + #endif + int rc = 0; +@@ -4148,7 +4141,7 @@ static struct smack_known *smack_from_netlbl(const struct sock *sk, u16 family, + netlbl_secattr_init(&secattr); + + if (sk) +- ssp = sk->sk_security; ++ ssp = smack_sock(sk); + + if (netlbl_skbuff_getattr(skb, family, &secattr) == 0) { + skp = smack_from_secattr(&secattr, ssp); +@@ -4170,7 +4163,7 @@ static struct smack_known *smack_from_netlbl(const struct sock *sk, u16 family, + */ + static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) + { +- struct socket_smack *ssp = sk->sk_security; ++ struct socket_smack *ssp = smack_sock(sk); + struct smack_known *skp = NULL; + int rc = 0; + struct smk_audit_info ad; +@@ -4274,7 +4267,7 @@ static int smack_socket_getpeersec_stream(struct socket *sock, + u32 slen = 1; + int rc = 0; + +- ssp = sock->sk->sk_security; ++ ssp = smack_sock(sock->sk); + if (ssp->smk_packet != NULL) { + rcp = ssp->smk_packet->smk_known; + slen = strlen(rcp) + 1; +@@ -4324,7 +4317,7 @@ static int smack_socket_getpeersec_dgram(struct socket *sock, + + switch (family) { + case PF_UNIX: +- ssp = sock->sk->sk_security; ++ ssp = smack_sock(sock->sk); + s = ssp->smk_out->smk_secid; + break; + case PF_INET: +@@ -4373,7 +4366,7 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent) + (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)) + return; + +- ssp = sk->sk_security; ++ ssp = smack_sock(sk); + ssp->smk_in = skp; + ssp->smk_out = skp; + /* cssp->smk_packet is already set in smack_inet_csk_clone() */ +@@ -4393,7 +4386,7 @@ static int smack_inet_conn_request(const struct sock *sk, struct sk_buff *skb, + { + u16 family = sk->sk_family; + struct smack_known *skp; +- struct socket_smack *ssp = sk->sk_security; ++ struct socket_smack *ssp = smack_sock(sk); + struct sockaddr_in addr; + struct iphdr *hdr; + struct smack_known *hskp; +@@ -4479,7 +4472,7 @@ static int smack_inet_conn_request(const struct sock *sk, struct sk_buff *skb, + static void smack_inet_csk_clone(struct sock *sk, + const struct request_sock *req) + { +- struct socket_smack *ssp = sk->sk_security; ++ struct socket_smack *ssp = smack_sock(sk); + struct smack_known *skp; + + if (req->peer_secid != 0) { +@@ -5049,6 +5042,7 @@ struct lsm_blob_sizes smack_blob_sizes __ro_after_init = { + .lbs_inode = sizeof(struct inode_smack), + .lbs_ipc = sizeof(struct smack_known *), + .lbs_msg_msg = sizeof(struct smack_known *), ++ .lbs_sock = sizeof(struct socket_smack), + .lbs_superblock = sizeof(struct superblock_smack), + .lbs_xattr_count = SMACK_INODE_INIT_XATTRS, + }; +@@ -5173,7 +5167,9 @@ static struct security_hook_list smack_hooks[] __ro_after_init = { + LSM_HOOK_INIT(socket_getpeersec_stream, smack_socket_getpeersec_stream), + LSM_HOOK_INIT(socket_getpeersec_dgram, smack_socket_getpeersec_dgram), + LSM_HOOK_INIT(sk_alloc_security, smack_sk_alloc_security), ++#ifdef SMACK_IPV6_PORT_LABELING + LSM_HOOK_INIT(sk_free_security, smack_sk_free_security), ++#endif + LSM_HOOK_INIT(sk_clone_security, smack_sk_clone_security), + LSM_HOOK_INIT(sock_graft, smack_sock_graft), + LSM_HOOK_INIT(inet_conn_request, smack_inet_conn_request), +diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c +index b945c1d3a7431a..bad71b7e648da7 100644 +--- a/security/smack/smack_netfilter.c ++++ b/security/smack/smack_netfilter.c +@@ -26,8 +26,8 @@ static unsigned int smack_ip_output(void *priv, + struct socket_smack *ssp; + struct smack_known *skp; + +- if (sk && sk->sk_security) { +- ssp = sk->sk_security; ++ if (sk) { ++ ssp = smack_sock(sk); + skp = ssp->smk_out; + skb->secmark = skp->smk_secid; + } +diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c +index e22aad7604e8ac..5dd1e164f9b13d 100644 +--- a/security/smack/smackfs.c ++++ b/security/smack/smackfs.c +@@ -932,7 +932,7 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, + } + if (rc >= 0) { + old_cat = skp->smk_netlabel.attr.mls.cat; +- skp->smk_netlabel.attr.mls.cat = ncats.attr.mls.cat; ++ rcu_assign_pointer(skp->smk_netlabel.attr.mls.cat, ncats.attr.mls.cat); + skp->smk_netlabel.attr.mls.lvl = ncats.attr.mls.lvl; + synchronize_rcu(); + netlbl_catmap_free(old_cat); +diff --git a/sound/pci/hda/cs35l41_hda_spi.c b/sound/pci/hda/cs35l41_hda_spi.c +index b76c0dfd5fefc4..f8c356ad0d340f 100644 +--- a/sound/pci/hda/cs35l41_hda_spi.c ++++ b/sound/pci/hda/cs35l41_hda_spi.c +@@ -38,6 +38,7 @@ static const struct spi_device_id cs35l41_hda_spi_id[] = { + { "cs35l41-hda", 0 }, + {} + }; ++MODULE_DEVICE_TABLE(spi, cs35l41_hda_spi_id); + + static const struct acpi_device_id cs35l41_acpi_hda_match[] = { + { "CSC3551", 0 }, +diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c +index 9e88d39eac1e22..0676b416056607 100644 +--- a/sound/pci/hda/tas2781_hda_i2c.c ++++ b/sound/pci/hda/tas2781_hda_i2c.c +@@ -822,7 +822,7 @@ static int tas2781_hda_i2c_probe(struct i2c_client *clt) + } else + return -ENODEV; + +- tas_hda->priv->irq_info.irq = clt->irq; ++ tas_hda->priv->irq = clt->irq; + ret = tas2781_read_acpi(tas_hda->priv, device_name); + if (ret) + return dev_err_probe(tas_hda->dev, ret, +diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c +index e3aca9c785a079..aa163ec4086223 100644 +--- a/sound/soc/codecs/rt5682.c ++++ b/sound/soc/codecs/rt5682.c +@@ -2903,8 +2903,10 @@ int rt5682_register_dai_clks(struct rt5682_priv *rt5682) + } + + if (dev->of_node) { +- devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, ++ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, + dai_clk_hw); ++ if (ret) ++ return ret; + } else { + ret = devm_clk_hw_register_clkdev(dev, dai_clk_hw, + init.name, +diff --git a/sound/soc/codecs/rt5682s.c b/sound/soc/codecs/rt5682s.c +index f50f196d700d72..ce2e88e066f3e5 100644 +--- a/sound/soc/codecs/rt5682s.c ++++ b/sound/soc/codecs/rt5682s.c +@@ -2828,7 +2828,9 @@ static int rt5682s_register_dai_clks(struct snd_soc_component *component) + } + + if (dev->of_node) { +- devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, dai_clk_hw); ++ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, dai_clk_hw); ++ if (ret) ++ return ret; + } else { + ret = devm_clk_hw_register_clkdev(dev, dai_clk_hw, + init.name, dev_name(dev)); +diff --git a/sound/soc/codecs/tas2781-comlib.c b/sound/soc/codecs/tas2781-comlib.c +index 3aa81514dad76f..0444cf90c5119f 100644 +--- a/sound/soc/codecs/tas2781-comlib.c ++++ b/sound/soc/codecs/tas2781-comlib.c +@@ -14,7 +14,6 @@ + #include <linux/interrupt.h> + #include <linux/module.h> + #include <linux/of.h> +-#include <linux/of_gpio.h> + #include <linux/of_irq.h> + #include <linux/regmap.h> + #include <linux/slab.h> +@@ -406,8 +405,6 @@ EXPORT_SYMBOL_GPL(tasdevice_dsp_remove); + + void tasdevice_remove(struct tasdevice_priv *tas_priv) + { +- if (gpio_is_valid(tas_priv->irq_info.irq_gpio)) +- gpio_free(tas_priv->irq_info.irq_gpio); + mutex_destroy(&tas_priv->codec_lock); + } + EXPORT_SYMBOL_GPL(tasdevice_remove); +diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c +index 8f9a3ae7153e94..f3a7605f071043 100644 +--- a/sound/soc/codecs/tas2781-fmwlib.c ++++ b/sound/soc/codecs/tas2781-fmwlib.c +@@ -13,7 +13,6 @@ + #include <linux/interrupt.h> + #include <linux/module.h> + #include <linux/of.h> +-#include <linux/of_gpio.h> + #include <linux/of_irq.h> + #include <linux/regmap.h> + #include <linux/slab.h> +diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c +index c64d458e524e2c..edd1ad3062c886 100644 +--- a/sound/soc/codecs/tas2781-i2c.c ++++ b/sound/soc/codecs/tas2781-i2c.c +@@ -21,7 +21,7 @@ + #include <linux/interrupt.h> + #include <linux/module.h> + #include <linux/of.h> +-#include <linux/of_gpio.h> ++#include <linux/of_address.h> + #include <linux/of_irq.h> + #include <linux/regmap.h> + #include <linux/slab.h> +@@ -618,7 +618,7 @@ static void tasdevice_parse_dt(struct tasdevice_priv *tas_priv) + { + struct i2c_client *client = (struct i2c_client *)tas_priv->client; + unsigned int dev_addrs[TASDEVICE_MAX_CHANNELS]; +- int rc, i, ndev = 0; ++ int i, ndev = 0; + + if (tas_priv->isacpi) { + ndev = device_property_read_u32_array(&client->dev, +@@ -633,64 +633,34 @@ static void tasdevice_parse_dt(struct tasdevice_priv *tas_priv) + "ti,audio-slots", dev_addrs, ndev); + } + +- tas_priv->irq_info.irq_gpio = ++ tas_priv->irq = + acpi_dev_gpio_irq_get(ACPI_COMPANION(&client->dev), 0); +- } else { ++ } else if (IS_ENABLED(CONFIG_OF)) { + struct device_node *np = tas_priv->dev->of_node; +-#ifdef CONFIG_OF +- const __be32 *reg, *reg_end; +- int len, sw, aw; +- +- aw = of_n_addr_cells(np); +- sw = of_n_size_cells(np); +- if (sw == 0) { +- reg = (const __be32 *)of_get_property(np, +- "reg", &len); +- reg_end = reg + len/sizeof(*reg); +- ndev = 0; +- do { +- dev_addrs[ndev] = of_read_number(reg, aw); +- reg += aw; +- ndev++; +- } while (reg < reg_end); +- } else { +- ndev = 1; +- dev_addrs[0] = client->addr; ++ u64 addr; ++ ++ for (i = 0; i < TASDEVICE_MAX_CHANNELS; i++) { ++ if (of_property_read_reg(np, i, &addr, NULL)) ++ break; ++ dev_addrs[ndev++] = addr; + } +-#else ++ ++ tas_priv->irq = of_irq_get(np, 0); ++ } else { + ndev = 1; + dev_addrs[0] = client->addr; +-#endif +- tas_priv->irq_info.irq_gpio = of_irq_get(np, 0); + } + tas_priv->ndev = ndev; + for (i = 0; i < ndev; i++) + tas_priv->tasdevice[i].dev_addr = dev_addrs[i]; + + tas_priv->reset = devm_gpiod_get_optional(&client->dev, +- "reset-gpios", GPIOD_OUT_HIGH); ++ "reset", GPIOD_OUT_HIGH); + if (IS_ERR(tas_priv->reset)) + dev_err(tas_priv->dev, "%s Can't get reset GPIO\n", + __func__); + + strcpy(tas_priv->dev_name, tasdevice_id[tas_priv->chip_id].name); +- +- if (gpio_is_valid(tas_priv->irq_info.irq_gpio)) { +- rc = gpio_request(tas_priv->irq_info.irq_gpio, +- "AUDEV-IRQ"); +- if (!rc) { +- gpio_direction_input( +- tas_priv->irq_info.irq_gpio); +- +- tas_priv->irq_info.irq = +- gpio_to_irq(tas_priv->irq_info.irq_gpio); +- } else +- dev_err(tas_priv->dev, "%s: GPIO %d request error\n", +- __func__, tas_priv->irq_info.irq_gpio); +- } else +- dev_err(tas_priv->dev, +- "Looking up irq-gpio property failed %d\n", +- tas_priv->irq_info.irq_gpio); + } + + static int tasdevice_i2c_probe(struct i2c_client *i2c) +diff --git a/sound/soc/loongson/loongson_card.c b/sound/soc/loongson/loongson_card.c +index fae5e9312bf08c..2c8dbdba27c5f8 100644 +--- a/sound/soc/loongson/loongson_card.c ++++ b/sound/soc/loongson/loongson_card.c +@@ -127,8 +127,8 @@ static int loongson_card_parse_of(struct loongson_card_data *data) + codec = of_get_child_by_name(dev->of_node, "codec"); + if (!codec) { + dev_err(dev, "audio-codec property missing or invalid\n"); +- ret = -EINVAL; +- goto err; ++ of_node_put(cpu); ++ return -EINVAL; + } + + for (i = 0; i < card->num_links; i++) { +diff --git a/tools/bpf/runqslower/Makefile b/tools/bpf/runqslower/Makefile +index d8288936c9120f..c4f1f1735af659 100644 +--- a/tools/bpf/runqslower/Makefile ++++ b/tools/bpf/runqslower/Makefile +@@ -15,6 +15,7 @@ INCLUDES := -I$(OUTPUT) -I$(BPF_INCLUDE) -I$(abspath ../../include/uapi) + CFLAGS := -g -Wall $(CLANG_CROSS_FLAGS) + CFLAGS += $(EXTRA_CFLAGS) + LDFLAGS += $(EXTRA_LDFLAGS) ++LDLIBS += -lelf -lz + + # Try to detect best kernel BTF source + KERNEL_REL := $(shell uname -r) +@@ -51,7 +52,7 @@ clean: + libbpf_hdrs: $(BPFOBJ) + + $(OUTPUT)/runqslower: $(OUTPUT)/runqslower.o $(BPFOBJ) +- $(QUIET_LINK)$(CC) $(CFLAGS) $^ -lelf -lz -o $@ ++ $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@ + + $(OUTPUT)/runqslower.o: runqslower.h $(OUTPUT)/runqslower.skel.h \ + $(OUTPUT)/runqslower.bpf.o | libbpf_hdrs +diff --git a/tools/build/feature/test-all.c b/tools/build/feature/test-all.c +index dd0a18c2ef8fc0..6f4bf386a3b5c4 100644 +--- a/tools/build/feature/test-all.c ++++ b/tools/build/feature/test-all.c +@@ -134,10 +134,6 @@ + #undef main + #endif + +-#define main main_test_libcapstone +-# include "test-libcapstone.c" +-#undef main +- + #define main main_test_lzma + # include "test-lzma.c" + #undef main +diff --git a/tools/include/nolibc/string.h b/tools/include/nolibc/string.h +index f9ab28421e6dcd..9ec9c24f38c092 100644 +--- a/tools/include/nolibc/string.h ++++ b/tools/include/nolibc/string.h +@@ -7,6 +7,7 @@ + #ifndef _NOLIBC_STRING_H + #define _NOLIBC_STRING_H + ++#include "arch.h" + #include "std.h" + + static void *malloc(size_t len); +diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c +index 5edb717647847b..3ecb33188336f6 100644 +--- a/tools/lib/bpf/libbpf.c ++++ b/tools/lib/bpf/libbpf.c +@@ -473,8 +473,6 @@ struct bpf_program { + }; + + struct bpf_struct_ops { +- const char *tname; +- const struct btf_type *type; + struct bpf_program **progs; + __u32 *kern_func_off; + /* e.g. struct tcp_congestion_ops in bpf_prog's btf format */ +@@ -1059,11 +1057,14 @@ static int bpf_object_adjust_struct_ops_autoload(struct bpf_object *obj) + continue; + + for (j = 0; j < obj->nr_maps; ++j) { ++ const struct btf_type *type; ++ + map = &obj->maps[j]; + if (!bpf_map__is_struct_ops(map)) + continue; + +- vlen = btf_vlen(map->st_ops->type); ++ type = btf__type_by_id(obj->btf, map->st_ops->type_id); ++ vlen = btf_vlen(type); + for (k = 0; k < vlen; ++k) { + slot_prog = map->st_ops->progs[k]; + if (prog != slot_prog) +@@ -1097,8 +1098,8 @@ static int bpf_map__init_kern_struct_ops(struct bpf_map *map) + int err; + + st_ops = map->st_ops; +- type = st_ops->type; +- tname = st_ops->tname; ++ type = btf__type_by_id(btf, st_ops->type_id); ++ tname = btf__name_by_offset(btf, type->name_off); + err = find_struct_ops_kern_types(obj, tname, &mod_btf, + &kern_type, &kern_type_id, + &kern_vtype, &kern_vtype_id, +@@ -1398,8 +1399,6 @@ static int init_struct_ops_maps(struct bpf_object *obj, const char *sec_name, + memcpy(st_ops->data, + data->d_buf + vsi->offset, + type->size); +- st_ops->tname = tname; +- st_ops->type = type; + st_ops->type_id = type_id; + + pr_debug("struct_ops init: struct %s(type_id=%u) %s found at offset %u\n", +@@ -7867,16 +7866,19 @@ static int bpf_object_init_progs(struct bpf_object *obj, const struct bpf_object + } + + static struct bpf_object *bpf_object_open(const char *path, const void *obj_buf, size_t obj_buf_sz, ++ const char *obj_name, + const struct bpf_object_open_opts *opts) + { +- const char *obj_name, *kconfig, *btf_tmp_path, *token_path; ++ const char *kconfig, *btf_tmp_path, *token_path; + struct bpf_object *obj; +- char tmp_name[64]; + int err; + char *log_buf; + size_t log_size; + __u32 log_level; + ++ if (obj_buf && !obj_name) ++ return ERR_PTR(-EINVAL); ++ + if (elf_version(EV_CURRENT) == EV_NONE) { + pr_warn("failed to init libelf for %s\n", + path ? : "(mem buf)"); +@@ -7886,16 +7888,12 @@ static struct bpf_object *bpf_object_open(const char *path, const void *obj_buf, + if (!OPTS_VALID(opts, bpf_object_open_opts)) + return ERR_PTR(-EINVAL); + +- obj_name = OPTS_GET(opts, object_name, NULL); ++ obj_name = OPTS_GET(opts, object_name, NULL) ?: obj_name; + if (obj_buf) { +- if (!obj_name) { +- snprintf(tmp_name, sizeof(tmp_name), "%lx-%lx", +- (unsigned long)obj_buf, +- (unsigned long)obj_buf_sz); +- obj_name = tmp_name; +- } + path = obj_name; + pr_debug("loading object '%s' from buffer\n", obj_name); ++ } else { ++ pr_debug("loading object from %s\n", path); + } + + log_buf = OPTS_GET(opts, kernel_log_buf, NULL); +@@ -7979,9 +7977,7 @@ bpf_object__open_file(const char *path, const struct bpf_object_open_opts *opts) + if (!path) + return libbpf_err_ptr(-EINVAL); + +- pr_debug("loading %s\n", path); +- +- return libbpf_ptr(bpf_object_open(path, NULL, 0, opts)); ++ return libbpf_ptr(bpf_object_open(path, NULL, 0, NULL, opts)); + } + + struct bpf_object *bpf_object__open(const char *path) +@@ -7993,10 +7989,15 @@ struct bpf_object * + bpf_object__open_mem(const void *obj_buf, size_t obj_buf_sz, + const struct bpf_object_open_opts *opts) + { ++ char tmp_name[64]; ++ + if (!obj_buf || obj_buf_sz == 0) + return libbpf_err_ptr(-EINVAL); + +- return libbpf_ptr(bpf_object_open(NULL, obj_buf, obj_buf_sz, opts)); ++ /* create a (quite useless) default "name" for this memory buffer object */ ++ snprintf(tmp_name, sizeof(tmp_name), "%lx-%zx", (unsigned long)obj_buf, obj_buf_sz); ++ ++ return libbpf_ptr(bpf_object_open(NULL, obj_buf, obj_buf_sz, tmp_name, opts)); + } + + static int bpf_object_unload(struct bpf_object *obj) +@@ -8406,11 +8407,13 @@ static int bpf_object__resolve_externs(struct bpf_object *obj, + + static void bpf_map_prepare_vdata(const struct bpf_map *map) + { ++ const struct btf_type *type; + struct bpf_struct_ops *st_ops; + __u32 i; + + st_ops = map->st_ops; +- for (i = 0; i < btf_vlen(st_ops->type); i++) { ++ type = btf__type_by_id(map->obj->btf, st_ops->type_id); ++ for (i = 0; i < btf_vlen(type); i++) { + struct bpf_program *prog = st_ops->progs[i]; + void *kern_data; + int prog_fd; +@@ -9673,6 +9676,7 @@ static struct bpf_map *find_struct_ops_map_by_offset(struct bpf_object *obj, + static int bpf_object__collect_st_ops_relos(struct bpf_object *obj, + Elf64_Shdr *shdr, Elf_Data *data) + { ++ const struct btf_type *type; + const struct btf_member *member; + struct bpf_struct_ops *st_ops; + struct bpf_program *prog; +@@ -9732,13 +9736,14 @@ static int bpf_object__collect_st_ops_relos(struct bpf_object *obj, + } + insn_idx = sym->st_value / BPF_INSN_SZ; + +- member = find_member_by_offset(st_ops->type, moff * 8); ++ type = btf__type_by_id(btf, st_ops->type_id); ++ member = find_member_by_offset(type, moff * 8); + if (!member) { + pr_warn("struct_ops reloc %s: cannot find member at moff %u\n", + map->name, moff); + return -EINVAL; + } +- member_idx = member - btf_members(st_ops->type); ++ member_idx = member - btf_members(type); + name = btf__name_by_offset(btf, member->name_off); + + if (!resolve_func_ptr(btf, member->type, NULL)) { +@@ -13715,29 +13720,13 @@ static int populate_skeleton_progs(const struct bpf_object *obj, + int bpf_object__open_skeleton(struct bpf_object_skeleton *s, + const struct bpf_object_open_opts *opts) + { +- DECLARE_LIBBPF_OPTS(bpf_object_open_opts, skel_opts, +- .object_name = s->name, +- ); + struct bpf_object *obj; + int err; + +- /* Attempt to preserve opts->object_name, unless overriden by user +- * explicitly. Overwriting object name for skeletons is discouraged, +- * as it breaks global data maps, because they contain object name +- * prefix as their own map name prefix. When skeleton is generated, +- * bpftool is making an assumption that this name will stay the same. +- */ +- if (opts) { +- memcpy(&skel_opts, opts, sizeof(*opts)); +- if (!opts->object_name) +- skel_opts.object_name = s->name; +- } +- +- obj = bpf_object__open_mem(s->data, s->data_sz, &skel_opts); +- err = libbpf_get_error(obj); +- if (err) { +- pr_warn("failed to initialize skeleton BPF object '%s': %d\n", +- s->name, err); ++ obj = bpf_object_open(NULL, s->data, s->data_sz, s->name, opts); ++ if (IS_ERR(obj)) { ++ err = PTR_ERR(obj); ++ pr_warn("failed to initialize skeleton BPF object '%s': %d\n", s->name, err); + return libbpf_err(err); + } + +diff --git a/tools/objtool/arch/loongarch/decode.c b/tools/objtool/arch/loongarch/decode.c +index aee479d2191c21..69b66994f2a155 100644 +--- a/tools/objtool/arch/loongarch/decode.c ++++ b/tools/objtool/arch/loongarch/decode.c +@@ -122,7 +122,7 @@ static bool decode_insn_reg2i12_fomat(union loongarch_instruction inst, + switch (inst.reg2i12_format.opcode) { + case addid_op: + if ((inst.reg2i12_format.rd == CFI_SP) || (inst.reg2i12_format.rj == CFI_SP)) { +- /* addi.d sp,sp,si12 or addi.d fp,sp,si12 */ ++ /* addi.d sp,sp,si12 or addi.d fp,sp,si12 or addi.d sp,fp,si12 */ + insn->immediate = sign_extend64(inst.reg2i12_format.immediate, 11); + ADD_OP(op) { + op->src.type = OP_SRC_ADD; +@@ -132,6 +132,15 @@ static bool decode_insn_reg2i12_fomat(union loongarch_instruction inst, + op->dest.reg = inst.reg2i12_format.rd; + } + } ++ if ((inst.reg2i12_format.rd == CFI_SP) && (inst.reg2i12_format.rj == CFI_FP)) { ++ /* addi.d sp,fp,si12 */ ++ struct symbol *func = find_func_containing(insn->sec, insn->offset); ++ ++ if (!func) ++ return false; ++ ++ func->frame_pointer = true; ++ } + break; + case ldd_op: + if (inst.reg2i12_format.rj == CFI_SP) { +diff --git a/tools/objtool/check.c b/tools/objtool/check.c +index 0a33d9195b7a91..60680b2bec96c0 100644 +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -2991,10 +2991,27 @@ static int update_cfi_state(struct instruction *insn, + break; + } + +- if (op->dest.reg == CFI_SP && op->src.reg == CFI_BP) { ++ if (op->dest.reg == CFI_BP && op->src.reg == CFI_SP && ++ insn->sym->frame_pointer) { ++ /* addi.d fp,sp,imm on LoongArch */ ++ if (cfa->base == CFI_SP && cfa->offset == op->src.offset) { ++ cfa->base = CFI_BP; ++ cfa->offset = 0; ++ } ++ break; ++ } + +- /* lea disp(%rbp), %rsp */ +- cfi->stack_size = -(op->src.offset + regs[CFI_BP].offset); ++ if (op->dest.reg == CFI_SP && op->src.reg == CFI_BP) { ++ /* addi.d sp,fp,imm on LoongArch */ ++ if (cfa->base == CFI_BP && cfa->offset == 0) { ++ if (insn->sym->frame_pointer) { ++ cfa->base = CFI_SP; ++ cfa->offset = -op->src.offset; ++ } ++ } else { ++ /* lea disp(%rbp), %rsp */ ++ cfi->stack_size = -(op->src.offset + regs[CFI_BP].offset); ++ } + break; + } + +diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h +index 2b8a69de4db871..d7e815c2fd1567 100644 +--- a/tools/objtool/include/objtool/elf.h ++++ b/tools/objtool/include/objtool/elf.h +@@ -68,6 +68,7 @@ struct symbol { + u8 warned : 1; + u8 embedded_insn : 1; + u8 local_label : 1; ++ u8 frame_pointer : 1; + struct list_head pv_target; + struct reloc *relocs; + }; +diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c +index c157bd31f2e5a4..7298f360706220 100644 +--- a/tools/perf/builtin-c2c.c ++++ b/tools/perf/builtin-c2c.c +@@ -3266,7 +3266,7 @@ static int perf_c2c__record(int argc, const char **argv) + return -1; + } + +- if (perf_pmu__mem_events_init(pmu)) { ++ if (perf_pmu__mem_events_init()) { + pr_err("failed: memory events not supported\n"); + return -1; + } +@@ -3290,19 +3290,15 @@ static int perf_c2c__record(int argc, const char **argv) + * PERF_MEM_EVENTS__LOAD_STORE if it is supported. + */ + if (e->tag) { +- e->record = true; ++ perf_mem_record[PERF_MEM_EVENTS__LOAD_STORE] = true; + rec_argv[i++] = "-W"; + } else { +- e = perf_pmu__mem_events_ptr(pmu, PERF_MEM_EVENTS__LOAD); +- e->record = true; +- +- e = perf_pmu__mem_events_ptr(pmu, PERF_MEM_EVENTS__STORE); +- e->record = true; ++ perf_mem_record[PERF_MEM_EVENTS__LOAD] = true; ++ perf_mem_record[PERF_MEM_EVENTS__STORE] = true; + } + } + +- e = perf_pmu__mem_events_ptr(pmu, PERF_MEM_EVENTS__LOAD); +- if (e->record) ++ if (perf_mem_record[PERF_MEM_EVENTS__LOAD]) + rec_argv[i++] = "-W"; + + rec_argv[i++] = "-d"; +diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c +index a212678d47beb1..c80fb0f60e611f 100644 +--- a/tools/perf/builtin-inject.c ++++ b/tools/perf/builtin-inject.c +@@ -2204,6 +2204,7 @@ int cmd_inject(int argc, const char **argv) + .finished_init = perf_event__repipe_op2_synth, + .compressed = perf_event__repipe_op4_synth, + .auxtrace = perf_event__repipe_auxtrace, ++ .dont_split_sample_group = true, + }, + .input_name = "-", + .samples = LIST_HEAD_INIT(inject.samples), +diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c +index 863fcd735daee9..08724fa508e14c 100644 +--- a/tools/perf/builtin-mem.c ++++ b/tools/perf/builtin-mem.c +@@ -97,7 +97,7 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem) + return -1; + } + +- if (perf_pmu__mem_events_init(pmu)) { ++ if (perf_pmu__mem_events_init()) { + pr_err("failed: memory events not supported\n"); + return -1; + } +@@ -126,22 +126,17 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem) + if (e->tag && + (mem->operation & MEM_OPERATION_LOAD) && + (mem->operation & MEM_OPERATION_STORE)) { +- e->record = true; ++ perf_mem_record[PERF_MEM_EVENTS__LOAD_STORE] = true; + rec_argv[i++] = "-W"; + } else { +- if (mem->operation & MEM_OPERATION_LOAD) { +- e = perf_pmu__mem_events_ptr(pmu, PERF_MEM_EVENTS__LOAD); +- e->record = true; +- } ++ if (mem->operation & MEM_OPERATION_LOAD) ++ perf_mem_record[PERF_MEM_EVENTS__LOAD] = true; + +- if (mem->operation & MEM_OPERATION_STORE) { +- e = perf_pmu__mem_events_ptr(pmu, PERF_MEM_EVENTS__STORE); +- e->record = true; +- } ++ if (mem->operation & MEM_OPERATION_STORE) ++ perf_mem_record[PERF_MEM_EVENTS__STORE] = true; + } + +- e = perf_pmu__mem_events_ptr(pmu, PERF_MEM_EVENTS__LOAD); +- if (e->record) ++ if (perf_mem_record[PERF_MEM_EVENTS__LOAD]) + rec_argv[i++] = "-W"; + + rec_argv[i++] = "-d"; +@@ -372,6 +367,7 @@ static int report_events(int argc, const char **argv, struct perf_mem *mem) + rep_argv[i] = argv[j]; + + ret = cmd_report(i, rep_argv); ++ free(new_sort_order); + free(rep_argv); + return ret; + } +diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c +index 69618fb0110b64..8bebaba56bc3f5 100644 +--- a/tools/perf/builtin-report.c ++++ b/tools/perf/builtin-report.c +@@ -565,6 +565,7 @@ static int evlist__tty_browse_hists(struct evlist *evlist, struct report *rep, c + struct hists *hists = evsel__hists(pos); + const char *evname = evsel__name(pos); + ++ i++; + if (symbol_conf.event_group && !evsel__is_group_leader(pos)) + continue; + +@@ -574,7 +575,7 @@ static int evlist__tty_browse_hists(struct evlist *evlist, struct report *rep, c + hists__fprintf_nr_sample_events(hists, rep, evname, stdout); + + if (rep->total_cycles_mode) { +- report__browse_block_hists(&rep->block_reports[i++].hist, ++ report__browse_block_hists(&rep->block_reports[i - 1].hist, + rep->min_percent, pos, NULL); + continue; + } +diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c +index 5977c49ae2c76b..ed11a20bc14935 100644 +--- a/tools/perf/builtin-sched.c ++++ b/tools/perf/builtin-sched.c +@@ -2596,9 +2596,12 @@ static int timehist_sched_change_event(struct perf_tool *tool, + * - previous sched event is out of window - we are done + * - sample time is beyond window user cares about - reset it + * to close out stats for time window interest ++ * - If tprev is 0, that is, sched_in event for current task is ++ * not recorded, cannot determine whether sched_in event is ++ * within time window interest - ignore it + */ + if (ptime->end) { +- if (tprev > ptime->end) ++ if (!tprev || tprev > ptime->end) + goto out; + + if (t > ptime->end) +@@ -3031,7 +3034,8 @@ static int perf_sched__timehist(struct perf_sched *sched) + + if (perf_time__parse_str(&sched->ptime, sched->time_str) != 0) { + pr_err("Invalid time string\n"); +- return -EINVAL; ++ err = -EINVAL; ++ goto out; + } + + if (timehist_check_attr(sched, evlist) != 0) +diff --git a/tools/perf/scripts/python/arm-cs-trace-disasm.py b/tools/perf/scripts/python/arm-cs-trace-disasm.py +index d973c2baed1c85..7aff02d84ffb3b 100755 +--- a/tools/perf/scripts/python/arm-cs-trace-disasm.py ++++ b/tools/perf/scripts/python/arm-cs-trace-disasm.py +@@ -192,17 +192,16 @@ def process_event(param_dict): + ip = sample["ip"] + addr = sample["addr"] + ++ if (options.verbose == True): ++ print("Event type: %s" % name) ++ print_sample(sample) ++ + # Initialize CPU data if it's empty, and directly return back + # if this is the first tracing event for this CPU. + if (cpu_data.get(str(cpu) + 'addr') == None): + cpu_data[str(cpu) + 'addr'] = addr + return + +- +- if (options.verbose == True): +- print("Event type: %s" % name) +- print_sample(sample) +- + # If cannot find dso so cannot dump assembler, bail out + if (dso == '[unknown]'): + return +diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c +index 965da6c0b5427e..79c1f2ae7affdc 100644 +--- a/tools/perf/util/annotate-data.c ++++ b/tools/perf/util/annotate-data.c +@@ -104,7 +104,7 @@ static void pr_debug_location(Dwarf_Die *die, u64 pc, int reg) + return; + + while ((off = dwarf_getlocations(&attr, off, &base, &start, &end, &ops, &nops)) > 0) { +- if (reg != DWARF_REG_PC && end < pc) ++ if (reg != DWARF_REG_PC && end <= pc) + continue; + if (reg != DWARF_REG_PC && start > pc) + break; +diff --git a/tools/perf/util/bpf_skel/lock_data.h b/tools/perf/util/bpf_skel/lock_data.h +index 36af11faad03c1..de12892f992f8d 100644 +--- a/tools/perf/util/bpf_skel/lock_data.h ++++ b/tools/perf/util/bpf_skel/lock_data.h +@@ -7,11 +7,11 @@ struct tstamp_data { + u64 timestamp; + u64 lock; + u32 flags; +- u32 stack_id; ++ s32 stack_id; + }; + + struct contention_key { +- u32 stack_id; ++ s32 stack_id; + u32 pid; + u64 lock_addr_or_cgroup; + }; +diff --git a/tools/perf/util/bpf_skel/vmlinux/vmlinux.h b/tools/perf/util/bpf_skel/vmlinux/vmlinux.h +index e9028235d7717b..d818e30c545713 100644 +--- a/tools/perf/util/bpf_skel/vmlinux/vmlinux.h ++++ b/tools/perf/util/bpf_skel/vmlinux/vmlinux.h +@@ -15,6 +15,7 @@ + + typedef __u8 u8; + typedef __u32 u32; ++typedef __s32 s32; + typedef __u64 u64; + typedef __s64 s64; + +diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c +index 44ef968a7ad331..1b0e59f4d8e936 100644 +--- a/tools/perf/util/dwarf-aux.c ++++ b/tools/perf/util/dwarf-aux.c +@@ -1444,7 +1444,7 @@ static int __die_find_var_reg_cb(Dwarf_Die *die_mem, void *arg) + + while ((off = dwarf_getlocations(&attr, off, &base, &start, &end, &ops, &nops)) > 0) { + /* Assuming the location list is sorted by address */ +- if (end < data->pc) ++ if (end <= data->pc) + continue; + if (start > data->pc) + break; +@@ -1598,6 +1598,9 @@ static int __die_collect_vars_cb(Dwarf_Die *die_mem, void *arg) + if (dwarf_getlocations(&attr, 0, &base, &start, &end, &ops, &nops) <= 0) + return DIE_FIND_CB_SIBLING; + ++ if (!check_allowed_ops(ops, nops)) ++ return DIE_FIND_CB_SIBLING; ++ + if (die_get_real_type(die_mem, &type_die) == NULL) + return DIE_FIND_CB_SIBLING; + +@@ -1974,8 +1977,15 @@ static int __die_find_member_offset_cb(Dwarf_Die *die_mem, void *arg) + return DIE_FIND_CB_SIBLING; + + /* Unions might not have location */ +- if (die_get_data_member_location(die_mem, &loc) < 0) +- loc = 0; ++ if (die_get_data_member_location(die_mem, &loc) < 0) { ++ Dwarf_Attribute attr; ++ ++ if (dwarf_attr_integrate(die_mem, DW_AT_data_bit_offset, &attr) && ++ dwarf_formudata(&attr, &loc) == 0) ++ loc /= 8; ++ else ++ loc = 0; ++ } + + if (offset == loc) + return DIE_FIND_CB_END; +diff --git a/tools/perf/util/mem-events.c b/tools/perf/util/mem-events.c +index 6dda47bb774faa..1f1e1063efe378 100644 +--- a/tools/perf/util/mem-events.c ++++ b/tools/perf/util/mem-events.c +@@ -28,6 +28,8 @@ struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = { + }; + #undef E + ++bool perf_mem_record[PERF_MEM_EVENTS__MAX] = { 0 }; ++ + static char mem_loads_name[100]; + static char mem_stores_name[100]; + +@@ -162,7 +164,7 @@ int perf_pmu__mem_events_parse(struct perf_pmu *pmu, const char *str) + continue; + + if (strstr(e->tag, tok)) +- e->record = found = true; ++ perf_mem_record[j] = found = true; + } + + tok = strtok_r(NULL, ",", &saveptr); +@@ -191,7 +193,7 @@ static bool perf_pmu__mem_events_supported(const char *mnt, struct perf_pmu *pmu + return !stat(path, &st); + } + +-int perf_pmu__mem_events_init(struct perf_pmu *pmu) ++static int __perf_pmu__mem_events_init(struct perf_pmu *pmu) + { + const char *mnt = sysfs__mount(); + bool found = false; +@@ -218,6 +220,18 @@ int perf_pmu__mem_events_init(struct perf_pmu *pmu) + return found ? 0 : -ENOENT; + } + ++int perf_pmu__mem_events_init(void) ++{ ++ struct perf_pmu *pmu = NULL; ++ ++ while ((pmu = perf_pmus__scan_mem(pmu)) != NULL) { ++ if (__perf_pmu__mem_events_init(pmu)) ++ return -ENOENT; ++ } ++ ++ return 0; ++} ++ + void perf_pmu__mem_events_list(struct perf_pmu *pmu) + { + int j; +@@ -247,7 +261,7 @@ int perf_mem_events__record_args(const char **rec_argv, int *argv_nr) + for (int j = 0; j < PERF_MEM_EVENTS__MAX; j++) { + e = perf_pmu__mem_events_ptr(pmu, j); + +- if (!e->record) ++ if (!perf_mem_record[j]) + continue; + + if (!e->supported) { +diff --git a/tools/perf/util/mem-events.h b/tools/perf/util/mem-events.h +index ca31014d7934f4..8dc27db9fd52f4 100644 +--- a/tools/perf/util/mem-events.h ++++ b/tools/perf/util/mem-events.h +@@ -6,7 +6,6 @@ + #include <linux/types.h> + + struct perf_mem_event { +- bool record; + bool supported; + bool ldlat; + u32 aux_event; +@@ -28,9 +27,10 @@ struct perf_pmu; + + extern unsigned int perf_mem_events__loads_ldlat; + extern struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX]; ++extern bool perf_mem_record[PERF_MEM_EVENTS__MAX]; + + int perf_pmu__mem_events_parse(struct perf_pmu *pmu, const char *str); +-int perf_pmu__mem_events_init(struct perf_pmu *pmu); ++int perf_pmu__mem_events_init(void); + + struct perf_mem_event *perf_pmu__mem_events_ptr(struct perf_pmu *pmu, int i); + struct perf_pmu *perf_mem_events_find_pmu(void); +diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c +index a10343b9dcd419..1457cd5288abc8 100644 +--- a/tools/perf/util/session.c ++++ b/tools/perf/util/session.c +@@ -1511,6 +1511,9 @@ static int deliver_sample_group(struct evlist *evlist, + int ret = -EINVAL; + struct sample_read_value *v = sample->read.group.values; + ++ if (tool->dont_split_sample_group) ++ return deliver_sample_value(evlist, tool, event, sample, v, machine); ++ + sample_read_group__for_each(v, sample->read.group.nr, read_format) { + ret = deliver_sample_value(evlist, tool, event, sample, v, + machine); +diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c +index 186305fd2d0efa..ac79ac4ccbe022 100644 +--- a/tools/perf/util/stat-display.c ++++ b/tools/perf/util/stat-display.c +@@ -1226,7 +1226,8 @@ static void print_metric_headers(struct perf_stat_config *config, + + /* Print metrics headers only */ + evlist__for_each_entry(evlist, counter) { +- if (config->aggr_mode != AGGR_NONE && counter->metric_leader != counter) ++ if (!config->iostat_run && ++ config->aggr_mode != AGGR_NONE && counter->metric_leader != counter) + continue; + + os.evsel = counter; +diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c +index 30244392168163..1b91ccd4d52348 100644 +--- a/tools/perf/util/time-utils.c ++++ b/tools/perf/util/time-utils.c +@@ -20,7 +20,7 @@ int parse_nsec_time(const char *str, u64 *ptime) + u64 time_sec, time_nsec; + char *end; + +- time_sec = strtoul(str, &end, 10); ++ time_sec = strtoull(str, &end, 10); + if (*end != '.' && *end != '\0') + return -1; + +@@ -38,7 +38,7 @@ int parse_nsec_time(const char *str, u64 *ptime) + for (i = strlen(nsec_buf); i < 9; i++) + nsec_buf[i] = '0'; + +- time_nsec = strtoul(nsec_buf, &end, 10); ++ time_nsec = strtoull(nsec_buf, &end, 10); + if (*end != '\0') + return -1; + } else +diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h +index c957fb849ac633..62bbc9cec151bb 100644 +--- a/tools/perf/util/tool.h ++++ b/tools/perf/util/tool.h +@@ -85,6 +85,7 @@ struct perf_tool { + bool namespace_events; + bool cgroup_events; + bool no_warn; ++ bool dont_split_sample_group; + enum show_feature_header show_feat_hdr; + }; + +diff --git a/tools/power/cpupower/lib/powercap.c b/tools/power/cpupower/lib/powercap.c +index a7a59c6bacda81..94a0c69e55ef5e 100644 +--- a/tools/power/cpupower/lib/powercap.c ++++ b/tools/power/cpupower/lib/powercap.c +@@ -77,6 +77,14 @@ int powercap_get_enabled(int *mode) + return sysfs_get_enabled(path, mode); + } + ++/* ++ * TODO: implement function. Returns dummy 0 for now. ++ */ ++int powercap_set_enabled(int mode) ++{ ++ return 0; ++} ++ + /* + * Hardcoded, because rapl is the only powercap implementation + - * this needs to get more generic if more powercap implementations +diff --git a/tools/testing/selftests/arm64/signal/Makefile b/tools/testing/selftests/arm64/signal/Makefile +index 8f5febaf1a9a25..edb3613513b8a8 100644 +--- a/tools/testing/selftests/arm64/signal/Makefile ++++ b/tools/testing/selftests/arm64/signal/Makefile +@@ -23,7 +23,7 @@ $(TEST_GEN_PROGS): $(PROGS) + # Common test-unit targets to build common-layout test-cases executables + # Needs secondary expansion to properly include the testcase c-file in pre-reqs + COMMON_SOURCES := test_signals.c test_signals_utils.c testcases/testcases.c \ +- signals.S ++ signals.S sve_helpers.c + COMMON_HEADERS := test_signals.h test_signals_utils.h testcases/testcases.h + + .SECONDEXPANSION: +diff --git a/tools/testing/selftests/arm64/signal/sve_helpers.c b/tools/testing/selftests/arm64/signal/sve_helpers.c +new file mode 100644 +index 00000000000000..0acc121af3062a +--- /dev/null ++++ b/tools/testing/selftests/arm64/signal/sve_helpers.c +@@ -0,0 +1,56 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2024 ARM Limited ++ * ++ * Common helper functions for SVE and SME functionality. ++ */ ++ ++#include <stdbool.h> ++#include <kselftest.h> ++#include <asm/sigcontext.h> ++#include <sys/prctl.h> ++ ++unsigned int vls[SVE_VQ_MAX]; ++unsigned int nvls; ++ ++int sve_fill_vls(bool use_sme, int min_vls) ++{ ++ int vq, vl; ++ int pr_set_vl = use_sme ? PR_SME_SET_VL : PR_SVE_SET_VL; ++ int len_mask = use_sme ? PR_SME_VL_LEN_MASK : PR_SVE_VL_LEN_MASK; ++ ++ /* ++ * Enumerate up to SVE_VQ_MAX vector lengths ++ */ ++ for (vq = SVE_VQ_MAX; vq > 0; --vq) { ++ vl = prctl(pr_set_vl, vq * 16); ++ if (vl == -1) ++ return KSFT_FAIL; ++ ++ vl &= len_mask; ++ ++ /* ++ * Unlike SVE, SME does not require the minimum vector length ++ * to be implemented, or the VLs to be consecutive, so any call ++ * to the prctl might return the single implemented VL, which ++ * might be larger than 16. So to avoid this loop never ++ * terminating, bail out here when we find a higher VL than ++ * we asked for. ++ * See the ARM ARM, DDI 0487K.a, B1.4.2: I_QQRNR and I_NWYBP. ++ */ ++ if (vq < sve_vq_from_vl(vl)) ++ break; ++ ++ /* Skip missing VLs */ ++ vq = sve_vq_from_vl(vl); ++ ++ vls[nvls++] = vl; ++ } ++ ++ if (nvls < min_vls) { ++ fprintf(stderr, "Only %d VL supported\n", nvls); ++ return KSFT_SKIP; ++ } ++ ++ return KSFT_PASS; ++} +diff --git a/tools/testing/selftests/arm64/signal/sve_helpers.h b/tools/testing/selftests/arm64/signal/sve_helpers.h +new file mode 100644 +index 00000000000000..50948ce471cc62 +--- /dev/null ++++ b/tools/testing/selftests/arm64/signal/sve_helpers.h +@@ -0,0 +1,21 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2024 ARM Limited ++ * ++ * Common helper functions for SVE and SME functionality. ++ */ ++ ++#ifndef __SVE_HELPERS_H__ ++#define __SVE_HELPERS_H__ ++ ++#include <stdbool.h> ++ ++#define VLS_USE_SVE false ++#define VLS_USE_SME true ++ ++extern unsigned int vls[]; ++extern unsigned int nvls; ++ ++int sve_fill_vls(bool use_sme, int min_vls); ++ ++#endif +diff --git a/tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sme_change_vl.c b/tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sme_change_vl.c +index ebd5815b54bbaa..dfd6a2badf9fb3 100644 +--- a/tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sme_change_vl.c ++++ b/tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sme_change_vl.c +@@ -6,44 +6,28 @@ + * handler, this is not supported and is expected to segfault. + */ + ++#include <kselftest.h> + #include <signal.h> + #include <ucontext.h> + #include <sys/prctl.h> + + #include "test_signals_utils.h" ++#include "sve_helpers.h" + #include "testcases.h" + + struct fake_sigframe sf; +-static unsigned int vls[SVE_VQ_MAX]; +-unsigned int nvls = 0; + + static bool sme_get_vls(struct tdescr *td) + { +- int vq, vl; ++ int res = sve_fill_vls(VLS_USE_SME, 2); + +- /* +- * Enumerate up to SVE_VQ_MAX vector lengths +- */ +- for (vq = SVE_VQ_MAX; vq > 0; --vq) { +- vl = prctl(PR_SVE_SET_VL, vq * 16); +- if (vl == -1) +- return false; ++ if (!res) ++ return true; + +- vl &= PR_SME_VL_LEN_MASK; ++ if (res == KSFT_SKIP) ++ td->result = KSFT_SKIP; + +- /* Skip missing VLs */ +- vq = sve_vq_from_vl(vl); +- +- vls[nvls++] = vl; +- } +- +- /* We need at least two VLs */ +- if (nvls < 2) { +- fprintf(stderr, "Only %d VL supported\n", nvls); +- return false; +- } +- +- return true; ++ return false; + } + + static int fake_sigreturn_ssve_change_vl(struct tdescr *td, +@@ -51,30 +35,30 @@ static int fake_sigreturn_ssve_change_vl(struct tdescr *td, + { + size_t resv_sz, offset; + struct _aarch64_ctx *head = GET_SF_RESV_HEAD(sf); +- struct sve_context *sve; ++ struct za_context *za; + + /* Get a signal context with a SME ZA frame in it */ + if (!get_current_context(td, &sf.uc, sizeof(sf.uc))) + return 1; + + resv_sz = GET_SF_RESV_SIZE(sf); +- head = get_header(head, SVE_MAGIC, resv_sz, &offset); ++ head = get_header(head, ZA_MAGIC, resv_sz, &offset); + if (!head) { +- fprintf(stderr, "No SVE context\n"); ++ fprintf(stderr, "No ZA context\n"); + return 1; + } + +- if (head->size != sizeof(struct sve_context)) { ++ if (head->size != sizeof(struct za_context)) { + fprintf(stderr, "Register data present, aborting\n"); + return 1; + } + +- sve = (struct sve_context *)head; ++ za = (struct za_context *)head; + + /* No changes are supported; init left us at minimum VL so go to max */ + fprintf(stderr, "Attempting to change VL from %d to %d\n", +- sve->vl, vls[0]); +- sve->vl = vls[0]; ++ za->vl, vls[0]); ++ za->vl = vls[0]; + + fake_sigreturn(&sf, sizeof(sf), 0); + +diff --git a/tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sve_change_vl.c b/tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sve_change_vl.c +index e2a452190511ff..e1ccf8f85a70c8 100644 +--- a/tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sve_change_vl.c ++++ b/tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sve_change_vl.c +@@ -12,40 +12,22 @@ + #include <sys/prctl.h> + + #include "test_signals_utils.h" ++#include "sve_helpers.h" + #include "testcases.h" + + struct fake_sigframe sf; +-static unsigned int vls[SVE_VQ_MAX]; +-unsigned int nvls = 0; + + static bool sve_get_vls(struct tdescr *td) + { +- int vq, vl; ++ int res = sve_fill_vls(VLS_USE_SVE, 2); + +- /* +- * Enumerate up to SVE_VQ_MAX vector lengths +- */ +- for (vq = SVE_VQ_MAX; vq > 0; --vq) { +- vl = prctl(PR_SVE_SET_VL, vq * 16); +- if (vl == -1) +- return false; ++ if (!res) ++ return true; + +- vl &= PR_SVE_VL_LEN_MASK; +- +- /* Skip missing VLs */ +- vq = sve_vq_from_vl(vl); +- +- vls[nvls++] = vl; +- } +- +- /* We need at least two VLs */ +- if (nvls < 2) { +- fprintf(stderr, "Only %d VL supported\n", nvls); ++ if (res == KSFT_SKIP) + td->result = KSFT_SKIP; +- return false; +- } + +- return true; ++ return false; + } + + static int fake_sigreturn_sve_change_vl(struct tdescr *td, +diff --git a/tools/testing/selftests/arm64/signal/testcases/ssve_regs.c b/tools/testing/selftests/arm64/signal/testcases/ssve_regs.c +index 3d37daafcff513..6dbe48cf8b09ed 100644 +--- a/tools/testing/selftests/arm64/signal/testcases/ssve_regs.c ++++ b/tools/testing/selftests/arm64/signal/testcases/ssve_regs.c +@@ -6,51 +6,31 @@ + * set up as expected. + */ + ++#include <kselftest.h> + #include <signal.h> + #include <ucontext.h> + #include <sys/prctl.h> + + #include "test_signals_utils.h" ++#include "sve_helpers.h" + #include "testcases.h" + + static union { + ucontext_t uc; + char buf[1024 * 64]; + } context; +-static unsigned int vls[SVE_VQ_MAX]; +-unsigned int nvls = 0; + + static bool sme_get_vls(struct tdescr *td) + { +- int vq, vl; ++ int res = sve_fill_vls(VLS_USE_SME, 1); + +- /* +- * Enumerate up to SVE_VQ_MAX vector lengths +- */ +- for (vq = SVE_VQ_MAX; vq > 0; --vq) { +- vl = prctl(PR_SME_SET_VL, vq * 16); +- if (vl == -1) +- return false; +- +- vl &= PR_SME_VL_LEN_MASK; +- +- /* Did we find the lowest supported VL? */ +- if (vq < sve_vq_from_vl(vl)) +- break; ++ if (!res) ++ return true; + +- /* Skip missing VLs */ +- vq = sve_vq_from_vl(vl); +- +- vls[nvls++] = vl; +- } +- +- /* We need at least one VL */ +- if (nvls < 1) { +- fprintf(stderr, "Only %d VL supported\n", nvls); +- return false; +- } ++ if (res == KSFT_SKIP) ++ td->result = KSFT_SKIP; + +- return true; ++ return false; + } + + static void setup_ssve_regs(void) +diff --git a/tools/testing/selftests/arm64/signal/testcases/ssve_za_regs.c b/tools/testing/selftests/arm64/signal/testcases/ssve_za_regs.c +index 9dc5f128bbc0d5..5557e116e97363 100644 +--- a/tools/testing/selftests/arm64/signal/testcases/ssve_za_regs.c ++++ b/tools/testing/selftests/arm64/signal/testcases/ssve_za_regs.c +@@ -6,51 +6,31 @@ + * signal frames is set up as expected when enabled simultaneously. + */ + ++#include <kselftest.h> + #include <signal.h> + #include <ucontext.h> + #include <sys/prctl.h> + + #include "test_signals_utils.h" ++#include "sve_helpers.h" + #include "testcases.h" + + static union { + ucontext_t uc; + char buf[1024 * 128]; + } context; +-static unsigned int vls[SVE_VQ_MAX]; +-unsigned int nvls = 0; + + static bool sme_get_vls(struct tdescr *td) + { +- int vq, vl; ++ int res = sve_fill_vls(VLS_USE_SME, 1); + +- /* +- * Enumerate up to SVE_VQ_MAX vector lengths +- */ +- for (vq = SVE_VQ_MAX; vq > 0; --vq) { +- vl = prctl(PR_SME_SET_VL, vq * 16); +- if (vl == -1) +- return false; +- +- vl &= PR_SME_VL_LEN_MASK; +- +- /* Did we find the lowest supported VL? */ +- if (vq < sve_vq_from_vl(vl)) +- break; ++ if (!res) ++ return true; + +- /* Skip missing VLs */ +- vq = sve_vq_from_vl(vl); +- +- vls[nvls++] = vl; +- } +- +- /* We need at least one VL */ +- if (nvls < 1) { +- fprintf(stderr, "Only %d VL supported\n", nvls); +- return false; +- } ++ if (res == KSFT_SKIP) ++ td->result = KSFT_SKIP; + +- return true; ++ return false; + } + + static void setup_regs(void) +diff --git a/tools/testing/selftests/arm64/signal/testcases/sve_regs.c b/tools/testing/selftests/arm64/signal/testcases/sve_regs.c +index 8b16eabbb7697e..8143eb1c58c187 100644 +--- a/tools/testing/selftests/arm64/signal/testcases/sve_regs.c ++++ b/tools/testing/selftests/arm64/signal/testcases/sve_regs.c +@@ -6,47 +6,31 @@ + * expected. + */ + ++#include <kselftest.h> + #include <signal.h> + #include <ucontext.h> + #include <sys/prctl.h> + + #include "test_signals_utils.h" ++#include "sve_helpers.h" + #include "testcases.h" + + static union { + ucontext_t uc; + char buf[1024 * 64]; + } context; +-static unsigned int vls[SVE_VQ_MAX]; +-unsigned int nvls = 0; + + static bool sve_get_vls(struct tdescr *td) + { +- int vq, vl; ++ int res = sve_fill_vls(VLS_USE_SVE, 1); + +- /* +- * Enumerate up to SVE_VQ_MAX vector lengths +- */ +- for (vq = SVE_VQ_MAX; vq > 0; --vq) { +- vl = prctl(PR_SVE_SET_VL, vq * 16); +- if (vl == -1) +- return false; +- +- vl &= PR_SVE_VL_LEN_MASK; +- +- /* Skip missing VLs */ +- vq = sve_vq_from_vl(vl); ++ if (!res) ++ return true; + +- vls[nvls++] = vl; +- } +- +- /* We need at least one VL */ +- if (nvls < 1) { +- fprintf(stderr, "Only %d VL supported\n", nvls); +- return false; +- } ++ if (res == KSFT_SKIP) ++ td->result = KSFT_SKIP; + +- return true; ++ return false; + } + + static void setup_sve_regs(void) +diff --git a/tools/testing/selftests/arm64/signal/testcases/za_no_regs.c b/tools/testing/selftests/arm64/signal/testcases/za_no_regs.c +index 4d6f94b6178f36..ce26e9c2fa5e34 100644 +--- a/tools/testing/selftests/arm64/signal/testcases/za_no_regs.c ++++ b/tools/testing/selftests/arm64/signal/testcases/za_no_regs.c +@@ -6,47 +6,31 @@ + * expected. + */ + ++#include <kselftest.h> + #include <signal.h> + #include <ucontext.h> + #include <sys/prctl.h> + + #include "test_signals_utils.h" ++#include "sve_helpers.h" + #include "testcases.h" + + static union { + ucontext_t uc; + char buf[1024 * 128]; + } context; +-static unsigned int vls[SVE_VQ_MAX]; +-unsigned int nvls = 0; + + static bool sme_get_vls(struct tdescr *td) + { +- int vq, vl; ++ int res = sve_fill_vls(VLS_USE_SME, 1); + +- /* +- * Enumerate up to SME_VQ_MAX vector lengths +- */ +- for (vq = SVE_VQ_MAX; vq > 0; --vq) { +- vl = prctl(PR_SME_SET_VL, vq * 16); +- if (vl == -1) +- return false; +- +- vl &= PR_SME_VL_LEN_MASK; +- +- /* Skip missing VLs */ +- vq = sve_vq_from_vl(vl); ++ if (!res) ++ return true; + +- vls[nvls++] = vl; +- } +- +- /* We need at least one VL */ +- if (nvls < 1) { +- fprintf(stderr, "Only %d VL supported\n", nvls); +- return false; +- } ++ if (res == KSFT_SKIP) ++ td->result = KSFT_SKIP; + +- return true; ++ return false; + } + + static int do_one_sme_vl(struct tdescr *td, siginfo_t *si, ucontext_t *uc, +diff --git a/tools/testing/selftests/arm64/signal/testcases/za_regs.c b/tools/testing/selftests/arm64/signal/testcases/za_regs.c +index 174ad665669647..b9e13f27f1f9aa 100644 +--- a/tools/testing/selftests/arm64/signal/testcases/za_regs.c ++++ b/tools/testing/selftests/arm64/signal/testcases/za_regs.c +@@ -6,51 +6,31 @@ + * expected. + */ + ++#include <kselftest.h> + #include <signal.h> + #include <ucontext.h> + #include <sys/prctl.h> + + #include "test_signals_utils.h" ++#include "sve_helpers.h" + #include "testcases.h" + + static union { + ucontext_t uc; + char buf[1024 * 128]; + } context; +-static unsigned int vls[SVE_VQ_MAX]; +-unsigned int nvls = 0; + + static bool sme_get_vls(struct tdescr *td) + { +- int vq, vl; ++ int res = sve_fill_vls(VLS_USE_SME, 1); + +- /* +- * Enumerate up to SME_VQ_MAX vector lengths +- */ +- for (vq = SVE_VQ_MAX; vq > 0; --vq) { +- vl = prctl(PR_SME_SET_VL, vq * 16); +- if (vl == -1) +- return false; +- +- vl &= PR_SME_VL_LEN_MASK; +- +- /* Did we find the lowest supported VL? */ +- if (vq < sve_vq_from_vl(vl)) +- break; ++ if (!res) ++ return true; + +- /* Skip missing VLs */ +- vq = sve_vq_from_vl(vl); +- +- vls[nvls++] = vl; +- } +- +- /* We need at least one VL */ +- if (nvls < 1) { +- fprintf(stderr, "Only %d VL supported\n", nvls); +- return false; +- } ++ if (res == KSFT_SKIP) ++ td->result = KSFT_SKIP; + +- return true; ++ return false; + } + + static void setup_za_regs(void) +diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile +index dd49c1d23a604c..88e8a316e7686a 100644 +--- a/tools/testing/selftests/bpf/Makefile ++++ b/tools/testing/selftests/bpf/Makefile +@@ -427,23 +427,24 @@ $(OUTPUT)/cgroup_getset_retval_hooks.o: cgroup_getset_retval_hooks.h + # $1 - input .c file + # $2 - output .o file + # $3 - CFLAGS ++# $4 - binary name + define CLANG_BPF_BUILD_RULE +- $(call msg,CLNG-BPF,$(TRUNNER_BINARY),$2) ++ $(call msg,CLNG-BPF,$4,$2) + $(Q)$(CLANG) $3 -O2 --target=bpf -c $1 -mcpu=v3 -o $2 + endef + # Similar to CLANG_BPF_BUILD_RULE, but with disabled alu32 + define CLANG_NOALU32_BPF_BUILD_RULE +- $(call msg,CLNG-BPF,$(TRUNNER_BINARY),$2) ++ $(call msg,CLNG-BPF,$4,$2) + $(Q)$(CLANG) $3 -O2 --target=bpf -c $1 -mcpu=v2 -o $2 + endef + # Similar to CLANG_BPF_BUILD_RULE, but with cpu-v4 + define CLANG_CPUV4_BPF_BUILD_RULE +- $(call msg,CLNG-BPF,$(TRUNNER_BINARY),$2) ++ $(call msg,CLNG-BPF,$4,$2) + $(Q)$(CLANG) $3 -O2 --target=bpf -c $1 -mcpu=v4 -o $2 + endef + # Build BPF object using GCC + define GCC_BPF_BUILD_RULE +- $(call msg,GCC-BPF,$(TRUNNER_BINARY),$2) ++ $(call msg,GCC-BPF,$4,$2) + $(Q)$(BPF_GCC) $3 -DBPF_NO_PRESERVE_ACCESS_INDEX -Wno-attributes -O2 -c $1 -o $2 + endef + +@@ -535,7 +536,7 @@ $(TRUNNER_BPF_OBJS): $(TRUNNER_OUTPUT)/%.bpf.o: \ + $$(call $(TRUNNER_BPF_BUILD_RULE),$$<,$$@, \ + $(TRUNNER_BPF_CFLAGS) \ + $$($$<-CFLAGS) \ +- $$($$<-$2-CFLAGS)) ++ $$($$<-$2-CFLAGS),$(TRUNNER_BINARY)) + + $(TRUNNER_BPF_SKELS): %.skel.h: %.bpf.o $(BPFTOOL) | $(TRUNNER_OUTPUT) + $$(call msg,GEN-SKEL,$(TRUNNER_BINARY),$$@) +@@ -762,6 +763,8 @@ $(OUTPUT)/veristat: $(OUTPUT)/veristat.o + $(call msg,BINARY,,$@) + $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $(filter %.a %.o,$^) $(LDLIBS) -o $@ + ++# Linking uprobe_multi can fail due to relocation overflows on mips. ++$(OUTPUT)/uprobe_multi: CFLAGS += $(if $(filter mips, $(ARCH)),-mxgot) + $(OUTPUT)/uprobe_multi: uprobe_multi.c + $(call msg,BINARY,,$@) + $(Q)$(CC) $(CFLAGS) -O0 $(LDFLAGS) $^ $(LDLIBS) -o $@ +diff --git a/tools/testing/selftests/bpf/bench.c b/tools/testing/selftests/bpf/bench.c +index 627b74ae041b52..90dc3aca32bd8f 100644 +--- a/tools/testing/selftests/bpf/bench.c ++++ b/tools/testing/selftests/bpf/bench.c +@@ -10,6 +10,7 @@ + #include <sys/sysinfo.h> + #include <signal.h> + #include "bench.h" ++#include "bpf_util.h" + #include "testing_helpers.h" + + struct env env = { +diff --git a/tools/testing/selftests/bpf/bench.h b/tools/testing/selftests/bpf/bench.h +index 68180d8f8558ec..005c401b3e2275 100644 +--- a/tools/testing/selftests/bpf/bench.h ++++ b/tools/testing/selftests/bpf/bench.h +@@ -10,6 +10,7 @@ + #include <math.h> + #include <time.h> + #include <sys/syscall.h> ++#include <limits.h> + + struct cpu_set { + bool *cpus; +diff --git a/tools/testing/selftests/bpf/map_tests/sk_storage_map.c b/tools/testing/selftests/bpf/map_tests/sk_storage_map.c +index 18405c3b7cee9a..af10c309359a77 100644 +--- a/tools/testing/selftests/bpf/map_tests/sk_storage_map.c ++++ b/tools/testing/selftests/bpf/map_tests/sk_storage_map.c +@@ -412,7 +412,7 @@ static void test_sk_storage_map_stress_free(void) + rlim_new.rlim_max = rlim_new.rlim_cur + 128; + err = setrlimit(RLIMIT_NOFILE, &rlim_new); + CHECK(err, "setrlimit(RLIMIT_NOFILE)", "rlim_new:%lu errno:%d", +- rlim_new.rlim_cur, errno); ++ (unsigned long) rlim_new.rlim_cur, errno); + } + + err = do_sk_storage_map_stress_free(); +diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_iter_setsockopt.c b/tools/testing/selftests/bpf/prog_tests/bpf_iter_setsockopt.c +index b52ff8ce34db82..16bed9dd8e6a30 100644 +--- a/tools/testing/selftests/bpf/prog_tests/bpf_iter_setsockopt.c ++++ b/tools/testing/selftests/bpf/prog_tests/bpf_iter_setsockopt.c +@@ -95,7 +95,7 @@ static unsigned short get_local_port(int fd) + struct sockaddr_in6 addr; + socklen_t addrlen = sizeof(addr); + +- if (!getsockname(fd, &addr, &addrlen)) ++ if (!getsockname(fd, (struct sockaddr *)&addr, &addrlen)) + return ntohs(addr.sin6_port); + + return 0; +diff --git a/tools/testing/selftests/bpf/prog_tests/core_reloc.c b/tools/testing/selftests/bpf/prog_tests/core_reloc.c +index 47f42e6801056b..26019313e1fc20 100644 +--- a/tools/testing/selftests/bpf/prog_tests/core_reloc.c ++++ b/tools/testing/selftests/bpf/prog_tests/core_reloc.c +@@ -1,4 +1,5 @@ + // SPDX-License-Identifier: GPL-2.0 ++#define _GNU_SOURCE + #include <test_progs.h> + #include "progs/core_reloc_types.h" + #include "bpf_testmod/bpf_testmod.h" +diff --git a/tools/testing/selftests/bpf/prog_tests/crypto_sanity.c b/tools/testing/selftests/bpf/prog_tests/crypto_sanity.c +index b1a3a49a822a7b..42bd07f7218dc3 100644 +--- a/tools/testing/selftests/bpf/prog_tests/crypto_sanity.c ++++ b/tools/testing/selftests/bpf/prog_tests/crypto_sanity.c +@@ -4,7 +4,6 @@ + #include <sys/types.h> + #include <sys/socket.h> + #include <net/if.h> +-#include <linux/in6.h> + #include <linux/if_alg.h> + + #include "test_progs.h" +diff --git a/tools/testing/selftests/bpf/prog_tests/decap_sanity.c b/tools/testing/selftests/bpf/prog_tests/decap_sanity.c +index dcb9e5070cc3d9..d79f398ec6b7c1 100644 +--- a/tools/testing/selftests/bpf/prog_tests/decap_sanity.c ++++ b/tools/testing/selftests/bpf/prog_tests/decap_sanity.c +@@ -4,7 +4,6 @@ + #include <sys/types.h> + #include <sys/socket.h> + #include <net/if.h> +-#include <linux/in6.h> + + #include "test_progs.h" + #include "network_helpers.h" +diff --git a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c +index 9e5f38739104bf..3171047414a7dc 100644 +--- a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c ++++ b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0 ++#define _GNU_SOURCE + #include <test_progs.h> + #include <network_helpers.h> +-#include <error.h> + #include <linux/if_tun.h> + #include <sys/uio.h> + +diff --git a/tools/testing/selftests/bpf/prog_tests/kfree_skb.c b/tools/testing/selftests/bpf/prog_tests/kfree_skb.c +index c07991544a789e..34f8822fd2219c 100644 +--- a/tools/testing/selftests/bpf/prog_tests/kfree_skb.c ++++ b/tools/testing/selftests/bpf/prog_tests/kfree_skb.c +@@ -1,4 +1,5 @@ + // SPDX-License-Identifier: GPL-2.0 ++#define _GNU_SOURCE + #include <test_progs.h> + #include <network_helpers.h> + #include "kfree_skb.skel.h" +diff --git a/tools/testing/selftests/bpf/prog_tests/lwt_redirect.c b/tools/testing/selftests/bpf/prog_tests/lwt_redirect.c +index 835a1d756c1662..b6e8d822e8e95f 100644 +--- a/tools/testing/selftests/bpf/prog_tests/lwt_redirect.c ++++ b/tools/testing/selftests/bpf/prog_tests/lwt_redirect.c +@@ -47,7 +47,6 @@ + #include <linux/if_ether.h> + #include <linux/if_packet.h> + #include <linux/if_tun.h> +-#include <linux/icmp.h> + #include <arpa/inet.h> + #include <unistd.h> + #include <errno.h> +diff --git a/tools/testing/selftests/bpf/prog_tests/lwt_reroute.c b/tools/testing/selftests/bpf/prog_tests/lwt_reroute.c +index 03825d2b45a8b7..6c50c0f63f4365 100644 +--- a/tools/testing/selftests/bpf/prog_tests/lwt_reroute.c ++++ b/tools/testing/selftests/bpf/prog_tests/lwt_reroute.c +@@ -49,6 +49,7 @@ + * is not crashed, it is considered successful. + */ + #define NETNS "ns_lwt_reroute" ++#include <netinet/in.h> + #include "lwt_helpers.h" + #include "network_helpers.h" + #include <linux/net_tstamp.h> +diff --git a/tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c b/tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c +index e72d75d6baa71e..c29787e092d66a 100644 +--- a/tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c ++++ b/tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c +@@ -11,7 +11,7 @@ + #include <sched.h> + #include <sys/wait.h> + #include <sys/mount.h> +-#include <sys/fcntl.h> ++#include <fcntl.h> + #include "network_helpers.h" + + #define STACK_SIZE (1024 * 1024) +diff --git a/tools/testing/selftests/bpf/prog_tests/parse_tcp_hdr_opt.c b/tools/testing/selftests/bpf/prog_tests/parse_tcp_hdr_opt.c +index daa952711d8fdf..e9c07d561ded6d 100644 +--- a/tools/testing/selftests/bpf/prog_tests/parse_tcp_hdr_opt.c ++++ b/tools/testing/selftests/bpf/prog_tests/parse_tcp_hdr_opt.c +@@ -1,5 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + ++#define _GNU_SOURCE + #include <test_progs.h> + #include <network_helpers.h> + #include "test_parse_tcp_hdr_opt.skel.h" +diff --git a/tools/testing/selftests/bpf/prog_tests/sk_lookup.c b/tools/testing/selftests/bpf/prog_tests/sk_lookup.c +index de2466547efe0f..a1ab0af004549b 100644 +--- a/tools/testing/selftests/bpf/prog_tests/sk_lookup.c ++++ b/tools/testing/selftests/bpf/prog_tests/sk_lookup.c +@@ -18,7 +18,6 @@ + #include <arpa/inet.h> + #include <assert.h> + #include <errno.h> +-#include <error.h> + #include <fcntl.h> + #include <sched.h> + #include <stdio.h> +diff --git a/tools/testing/selftests/bpf/prog_tests/tc_redirect.c b/tools/testing/selftests/bpf/prog_tests/tc_redirect.c +index b1073d36d77ac2..a80a83e0440e3f 100644 +--- a/tools/testing/selftests/bpf/prog_tests/tc_redirect.c ++++ b/tools/testing/selftests/bpf/prog_tests/tc_redirect.c +@@ -471,7 +471,7 @@ static int set_forwarding(bool enable) + + static int __rcv_tstamp(int fd, const char *expected, size_t s, __u64 *tstamp) + { +- struct __kernel_timespec pkt_ts = {}; ++ struct timespec pkt_ts = {}; + char ctl[CMSG_SPACE(sizeof(pkt_ts))]; + struct timespec now_ts; + struct msghdr msg = {}; +@@ -495,7 +495,7 @@ static int __rcv_tstamp(int fd, const char *expected, size_t s, __u64 *tstamp) + + cmsg = CMSG_FIRSTHDR(&msg); + if (cmsg && cmsg->cmsg_level == SOL_SOCKET && +- cmsg->cmsg_type == SO_TIMESTAMPNS_NEW) ++ cmsg->cmsg_type == SO_TIMESTAMPNS) + memcpy(&pkt_ts, CMSG_DATA(cmsg), sizeof(pkt_ts)); + + pkt_ns = pkt_ts.tv_sec * NSEC_PER_SEC + pkt_ts.tv_nsec; +@@ -537,9 +537,9 @@ static int wait_netstamp_needed_key(void) + if (!ASSERT_GE(srv_fd, 0, "start_server")) + goto done; + +- err = setsockopt(srv_fd, SOL_SOCKET, SO_TIMESTAMPNS_NEW, ++ err = setsockopt(srv_fd, SOL_SOCKET, SO_TIMESTAMPNS, + &opt, sizeof(opt)); +- if (!ASSERT_OK(err, "setsockopt(SO_TIMESTAMPNS_NEW)")) ++ if (!ASSERT_OK(err, "setsockopt(SO_TIMESTAMPNS)")) + goto done; + + cli_fd = connect_to_fd(srv_fd, TIMEOUT_MILLIS); +@@ -621,9 +621,9 @@ static void test_inet_dtime(int family, int type, const char *addr, __u16 port) + return; + + /* Ensure the kernel puts the (rcv) timestamp for all skb */ +- err = setsockopt(listen_fd, SOL_SOCKET, SO_TIMESTAMPNS_NEW, ++ err = setsockopt(listen_fd, SOL_SOCKET, SO_TIMESTAMPNS, + &opt, sizeof(opt)); +- if (!ASSERT_OK(err, "setsockopt(SO_TIMESTAMPNS_NEW)")) ++ if (!ASSERT_OK(err, "setsockopt(SO_TIMESTAMPNS)")) + goto done; + + if (type == SOCK_STREAM) { +diff --git a/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c b/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c +index f2b99d95d91607..c38784c1c066e6 100644 +--- a/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c ++++ b/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c +@@ -1,4 +1,5 @@ + // SPDX-License-Identifier: GPL-2.0 ++#define _GNU_SOURCE + #include <test_progs.h> + #include "cgroup_helpers.h" + #include "network_helpers.h" +diff --git a/tools/testing/selftests/bpf/prog_tests/user_ringbuf.c b/tools/testing/selftests/bpf/prog_tests/user_ringbuf.c +index e51721df14fc19..dfff6feac12c3c 100644 +--- a/tools/testing/selftests/bpf/prog_tests/user_ringbuf.c ++++ b/tools/testing/selftests/bpf/prog_tests/user_ringbuf.c +@@ -4,6 +4,7 @@ + #define _GNU_SOURCE + #include <linux/compiler.h> + #include <linux/ring_buffer.h> ++#include <linux/build_bug.h> + #include <pthread.h> + #include <stdio.h> + #include <stdlib.h> +diff --git a/tools/testing/selftests/bpf/progs/bpf_misc.h b/tools/testing/selftests/bpf/progs/bpf_misc.h +index fb2f5513e29e1c..20541a7cd8070d 100644 +--- a/tools/testing/selftests/bpf/progs/bpf_misc.h ++++ b/tools/testing/selftests/bpf/progs/bpf_misc.h +@@ -2,14 +2,17 @@ + #ifndef __BPF_MISC_H__ + #define __BPF_MISC_H__ + ++#define XSTR(s) STR(s) ++#define STR(s) #s ++ + /* This set of attributes controls behavior of the + * test_loader.c:test_loader__run_subtests(). + * + * The test_loader sequentially loads each program in a skeleton. + * Programs could be loaded in privileged and unprivileged modes. +- * - __success, __failure, __msg imply privileged mode; +- * - __success_unpriv, __failure_unpriv, __msg_unpriv imply +- * unprivileged mode. ++ * - __success, __failure, __msg, __regex imply privileged mode; ++ * - __success_unpriv, __failure_unpriv, __msg_unpriv, __regex_unpriv ++ * imply unprivileged mode. + * If combination of privileged and unprivileged attributes is present + * both modes are used. If none are present privileged mode is implied. + * +@@ -24,6 +27,12 @@ + * Multiple __msg attributes could be specified. + * __msg_unpriv Same as __msg but for unprivileged mode. + * ++ * __regex Same as __msg, but using a regular expression. ++ * __regex_unpriv Same as __msg_unpriv but using a regular expression. ++ * __xlated Expect a line in a disassembly log after verifier applies rewrites. ++ * Multiple __xlated attributes could be specified. ++ * __xlated_unpriv Same as __xlated but for unprivileged mode. ++ * + * __success Expect program load success in privileged mode. + * __success_unpriv Expect program load success in unprivileged mode. + * +@@ -57,12 +66,20 @@ + * __auxiliary Annotated program is not a separate test, but used as auxiliary + * for some other test cases and should always be loaded. + * __auxiliary_unpriv Same, but load program in unprivileged mode. ++ * ++ * __arch_* Specify on which architecture the test case should be tested. ++ * Several __arch_* annotations could be specified at once. ++ * When test case is not run on current arch it is marked as skipped. + */ +-#define __msg(msg) __attribute__((btf_decl_tag("comment:test_expect_msg=" msg))) ++#define __msg(msg) __attribute__((btf_decl_tag("comment:test_expect_msg=" XSTR(__COUNTER__) "=" msg))) ++#define __regex(regex) __attribute__((btf_decl_tag("comment:test_expect_regex=" XSTR(__COUNTER__) "=" regex))) ++#define __xlated(msg) __attribute__((btf_decl_tag("comment:test_expect_xlated=" XSTR(__COUNTER__) "=" msg))) + #define __failure __attribute__((btf_decl_tag("comment:test_expect_failure"))) + #define __success __attribute__((btf_decl_tag("comment:test_expect_success"))) + #define __description(desc) __attribute__((btf_decl_tag("comment:test_description=" desc))) +-#define __msg_unpriv(msg) __attribute__((btf_decl_tag("comment:test_expect_msg_unpriv=" msg))) ++#define __msg_unpriv(msg) __attribute__((btf_decl_tag("comment:test_expect_msg_unpriv=" XSTR(__COUNTER__) "=" msg))) ++#define __regex_unpriv(regex) __attribute__((btf_decl_tag("comment:test_expect_regex_unpriv=" XSTR(__COUNTER__) "=" regex))) ++#define __xlated_unpriv(msg) __attribute__((btf_decl_tag("comment:test_expect_xlated_unpriv=" XSTR(__COUNTER__) "=" msg))) + #define __failure_unpriv __attribute__((btf_decl_tag("comment:test_expect_failure_unpriv"))) + #define __success_unpriv __attribute__((btf_decl_tag("comment:test_expect_success_unpriv"))) + #define __log_level(lvl) __attribute__((btf_decl_tag("comment:test_log_level="#lvl))) +@@ -72,6 +89,10 @@ + #define __auxiliary __attribute__((btf_decl_tag("comment:test_auxiliary"))) + #define __auxiliary_unpriv __attribute__((btf_decl_tag("comment:test_auxiliary_unpriv"))) + #define __btf_path(path) __attribute__((btf_decl_tag("comment:test_btf_path=" path))) ++#define __arch(arch) __attribute__((btf_decl_tag("comment:test_arch=" arch))) ++#define __arch_x86_64 __arch("X86_64") ++#define __arch_arm64 __arch("ARM64") ++#define __arch_riscv64 __arch("RISCV64") + + /* Convenience macro for use with 'asm volatile' blocks */ + #define __naked __attribute__((naked)) +diff --git a/tools/testing/selftests/bpf/progs/cg_storage_multi.h b/tools/testing/selftests/bpf/progs/cg_storage_multi.h +index a0778fe7857a14..41d59f0ee606c7 100644 +--- a/tools/testing/selftests/bpf/progs/cg_storage_multi.h ++++ b/tools/testing/selftests/bpf/progs/cg_storage_multi.h +@@ -3,8 +3,6 @@ + #ifndef __PROGS_CG_STORAGE_MULTI_H + #define __PROGS_CG_STORAGE_MULTI_H + +-#include <asm/types.h> +- + struct cgroup_value { + __u32 egress_pkts; + __u32 ingress_pkts; +diff --git a/tools/testing/selftests/bpf/progs/test_libbpf_get_fd_by_id_opts.c b/tools/testing/selftests/bpf/progs/test_libbpf_get_fd_by_id_opts.c +index f5ac5f3e89196f..568816307f7125 100644 +--- a/tools/testing/selftests/bpf/progs/test_libbpf_get_fd_by_id_opts.c ++++ b/tools/testing/selftests/bpf/progs/test_libbpf_get_fd_by_id_opts.c +@@ -31,6 +31,7 @@ int BPF_PROG(check_access, struct bpf_map *map, fmode_t fmode) + + if (fmode & FMODE_WRITE) + return -EACCES; ++ barrier(); + + return 0; + } +diff --git a/tools/testing/selftests/bpf/progs/verifier_spill_fill.c b/tools/testing/selftests/bpf/progs/verifier_spill_fill.c +index 85e48069c9e616..d4b99c3b4719b2 100644 +--- a/tools/testing/selftests/bpf/progs/verifier_spill_fill.c ++++ b/tools/testing/selftests/bpf/progs/verifier_spill_fill.c +@@ -1213,10 +1213,10 @@ __success __log_level(2) + * - once for path entry - label 2; + * - once for path entry - label 1 - label 2. + */ +-__msg("r1 = *(u64 *)(r10 -8)") +-__msg("exit") +-__msg("r1 = *(u64 *)(r10 -8)") +-__msg("exit") ++__msg("8: (79) r1 = *(u64 *)(r10 -8)") ++__msg("9: (95) exit") ++__msg("from 2 to 7") ++__msg("8: safe") + __msg("processed 11 insns") + __flag(BPF_F_TEST_STATE_FREQ) + __naked void old_stack_misc_vs_cur_ctx_ptr(void) +diff --git a/tools/testing/selftests/bpf/test_cpp.cpp b/tools/testing/selftests/bpf/test_cpp.cpp +index dde0bb16e782e9..abc2a56ab26164 100644 +--- a/tools/testing/selftests/bpf/test_cpp.cpp ++++ b/tools/testing/selftests/bpf/test_cpp.cpp +@@ -6,6 +6,10 @@ + #include <bpf/libbpf.h> + #include <bpf/bpf.h> + #include <bpf/btf.h> ++ ++#ifndef _Bool ++#define _Bool bool ++#endif + #include "test_core_extern.skel.h" + #include "struct_ops_module.skel.h" + +diff --git a/tools/testing/selftests/bpf/test_loader.c b/tools/testing/selftests/bpf/test_loader.c +index 524c38e9cde48f..2150e9c9b53fb1 100644 +--- a/tools/testing/selftests/bpf/test_loader.c ++++ b/tools/testing/selftests/bpf/test_loader.c +@@ -2,10 +2,12 @@ + /* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */ + #include <linux/capability.h> + #include <stdlib.h> ++#include <regex.h> + #include <test_progs.h> + #include <bpf/btf.h> + + #include "autoconf_helper.h" ++#include "disasm_helpers.h" + #include "unpriv_helpers.h" + #include "cap_helpers.h" + +@@ -17,9 +19,13 @@ + #define TEST_TAG_EXPECT_FAILURE "comment:test_expect_failure" + #define TEST_TAG_EXPECT_SUCCESS "comment:test_expect_success" + #define TEST_TAG_EXPECT_MSG_PFX "comment:test_expect_msg=" ++#define TEST_TAG_EXPECT_REGEX_PFX "comment:test_expect_regex=" ++#define TEST_TAG_EXPECT_XLATED_PFX "comment:test_expect_xlated=" + #define TEST_TAG_EXPECT_FAILURE_UNPRIV "comment:test_expect_failure_unpriv" + #define TEST_TAG_EXPECT_SUCCESS_UNPRIV "comment:test_expect_success_unpriv" + #define TEST_TAG_EXPECT_MSG_PFX_UNPRIV "comment:test_expect_msg_unpriv=" ++#define TEST_TAG_EXPECT_REGEX_PFX_UNPRIV "comment:test_expect_regex_unpriv=" ++#define TEST_TAG_EXPECT_XLATED_PFX_UNPRIV "comment:test_expect_xlated_unpriv=" + #define TEST_TAG_LOG_LEVEL_PFX "comment:test_log_level=" + #define TEST_TAG_PROG_FLAGS_PFX "comment:test_prog_flags=" + #define TEST_TAG_DESCRIPTION_PFX "comment:test_description=" +@@ -28,6 +34,7 @@ + #define TEST_TAG_AUXILIARY "comment:test_auxiliary" + #define TEST_TAG_AUXILIARY_UNPRIV "comment:test_auxiliary_unpriv" + #define TEST_BTF_PATH "comment:test_btf_path=" ++#define TEST_TAG_ARCH "comment:test_arch=" + + /* Warning: duplicated in bpf_misc.h */ + #define POINTER_VALUE 0xcafe4all +@@ -46,11 +53,22 @@ enum mode { + UNPRIV = 2 + }; + ++struct expect_msg { ++ const char *substr; /* substring match */ ++ const char *regex_str; /* regex-based match */ ++ regex_t regex; ++}; ++ ++struct expected_msgs { ++ struct expect_msg *patterns; ++ size_t cnt; ++}; ++ + struct test_subspec { + char *name; + bool expect_failure; +- const char **expect_msgs; +- size_t expect_msg_cnt; ++ struct expected_msgs expect_msgs; ++ struct expected_msgs expect_xlated; + int retval; + bool execute; + }; +@@ -63,6 +81,7 @@ struct test_spec { + int log_level; + int prog_flags; + int mode_mask; ++ int arch_mask; + bool auxiliary; + bool valid; + }; +@@ -87,31 +106,64 @@ void test_loader_fini(struct test_loader *tester) + free(tester->log_buf); + } + ++static void free_msgs(struct expected_msgs *msgs) ++{ ++ int i; ++ ++ for (i = 0; i < msgs->cnt; i++) ++ if (msgs->patterns[i].regex_str) ++ regfree(&msgs->patterns[i].regex); ++ free(msgs->patterns); ++ msgs->patterns = NULL; ++ msgs->cnt = 0; ++} ++ + static void free_test_spec(struct test_spec *spec) + { ++ /* Deallocate expect_msgs arrays. */ ++ free_msgs(&spec->priv.expect_msgs); ++ free_msgs(&spec->unpriv.expect_msgs); ++ free_msgs(&spec->priv.expect_xlated); ++ free_msgs(&spec->unpriv.expect_xlated); ++ + free(spec->priv.name); + free(spec->unpriv.name); +- free(spec->priv.expect_msgs); +- free(spec->unpriv.expect_msgs); +- + spec->priv.name = NULL; + spec->unpriv.name = NULL; +- spec->priv.expect_msgs = NULL; +- spec->unpriv.expect_msgs = NULL; + } + +-static int push_msg(const char *msg, struct test_subspec *subspec) ++static int push_msg(const char *substr, const char *regex_str, struct expected_msgs *msgs) + { + void *tmp; ++ int regcomp_res; ++ char error_msg[100]; ++ struct expect_msg *msg; + +- tmp = realloc(subspec->expect_msgs, (1 + subspec->expect_msg_cnt) * sizeof(void *)); ++ tmp = realloc(msgs->patterns, ++ (1 + msgs->cnt) * sizeof(struct expect_msg)); + if (!tmp) { + ASSERT_FAIL("failed to realloc memory for messages\n"); + return -ENOMEM; + } +- subspec->expect_msgs = tmp; +- subspec->expect_msgs[subspec->expect_msg_cnt++] = msg; ++ msgs->patterns = tmp; ++ msg = &msgs->patterns[msgs->cnt]; ++ ++ if (substr) { ++ msg->substr = substr; ++ msg->regex_str = NULL; ++ } else { ++ msg->regex_str = regex_str; ++ msg->substr = NULL; ++ regcomp_res = regcomp(&msg->regex, regex_str, REG_EXTENDED|REG_NEWLINE); ++ if (regcomp_res != 0) { ++ regerror(regcomp_res, &msg->regex, error_msg, sizeof(error_msg)); ++ PRINT_FAIL("Regexp compilation error in '%s': '%s'\n", ++ regex_str, error_msg); ++ return -EINVAL; ++ } ++ } + ++ msgs->cnt += 1; + return 0; + } + +@@ -163,6 +215,41 @@ static void update_flags(int *flags, int flag, bool clear) + *flags |= flag; + } + ++/* Matches a string of form '<pfx>[^=]=.*' and returns it's suffix. ++ * Used to parse btf_decl_tag values. ++ * Such values require unique prefix because compiler does not add ++ * same __attribute__((btf_decl_tag(...))) twice. ++ * Test suite uses two-component tags for such cases: ++ * ++ * <pfx> __COUNTER__ '=' ++ * ++ * For example, two consecutive __msg tags '__msg("foo") __msg("foo")' ++ * would be encoded as: ++ * ++ * [18] DECL_TAG 'comment:test_expect_msg=0=foo' type_id=15 component_idx=-1 ++ * [19] DECL_TAG 'comment:test_expect_msg=1=foo' type_id=15 component_idx=-1 ++ * ++ * And the purpose of this function is to extract 'foo' from the above. ++ */ ++static const char *skip_dynamic_pfx(const char *s, const char *pfx) ++{ ++ const char *msg; ++ ++ if (strncmp(s, pfx, strlen(pfx)) != 0) ++ return NULL; ++ msg = s + strlen(pfx); ++ msg = strchr(msg, '='); ++ if (!msg) ++ return NULL; ++ return msg + 1; ++} ++ ++enum arch { ++ ARCH_X86_64 = 0x1, ++ ARCH_ARM64 = 0x2, ++ ARCH_RISCV64 = 0x4, ++}; ++ + /* Uses btf_decl_tag attributes to describe the expected test + * behavior, see bpf_misc.h for detailed description of each attribute + * and attribute combinations. +@@ -176,6 +263,7 @@ static int parse_test_spec(struct test_loader *tester, + bool has_unpriv_result = false; + bool has_unpriv_retval = false; + int func_id, i, err = 0; ++ u32 arch_mask = 0; + struct btf *btf; + + memset(spec, 0, sizeof(*spec)); +@@ -231,15 +319,33 @@ static int parse_test_spec(struct test_loader *tester, + } else if (strcmp(s, TEST_TAG_AUXILIARY_UNPRIV) == 0) { + spec->auxiliary = true; + spec->mode_mask |= UNPRIV; +- } else if (str_has_pfx(s, TEST_TAG_EXPECT_MSG_PFX)) { +- msg = s + sizeof(TEST_TAG_EXPECT_MSG_PFX) - 1; +- err = push_msg(msg, &spec->priv); ++ } else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_MSG_PFX))) { ++ err = push_msg(msg, NULL, &spec->priv.expect_msgs); ++ if (err) ++ goto cleanup; ++ spec->mode_mask |= PRIV; ++ } else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_MSG_PFX_UNPRIV))) { ++ err = push_msg(msg, NULL, &spec->unpriv.expect_msgs); ++ if (err) ++ goto cleanup; ++ spec->mode_mask |= UNPRIV; ++ } else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_REGEX_PFX))) { ++ err = push_msg(NULL, msg, &spec->priv.expect_msgs); ++ if (err) ++ goto cleanup; ++ spec->mode_mask |= PRIV; ++ } else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_REGEX_PFX_UNPRIV))) { ++ err = push_msg(NULL, msg, &spec->unpriv.expect_msgs); ++ if (err) ++ goto cleanup; ++ spec->mode_mask |= UNPRIV; ++ } else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_XLATED_PFX))) { ++ err = push_msg(msg, NULL, &spec->priv.expect_xlated); + if (err) + goto cleanup; + spec->mode_mask |= PRIV; +- } else if (str_has_pfx(s, TEST_TAG_EXPECT_MSG_PFX_UNPRIV)) { +- msg = s + sizeof(TEST_TAG_EXPECT_MSG_PFX_UNPRIV) - 1; +- err = push_msg(msg, &spec->unpriv); ++ } else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_XLATED_PFX_UNPRIV))) { ++ err = push_msg(msg, NULL, &spec->unpriv.expect_xlated); + if (err) + goto cleanup; + spec->mode_mask |= UNPRIV; +@@ -290,11 +396,26 @@ static int parse_test_spec(struct test_loader *tester, + goto cleanup; + update_flags(&spec->prog_flags, flags, clear); + } ++ } else if (str_has_pfx(s, TEST_TAG_ARCH)) { ++ val = s + sizeof(TEST_TAG_ARCH) - 1; ++ if (strcmp(val, "X86_64") == 0) { ++ arch_mask |= ARCH_X86_64; ++ } else if (strcmp(val, "ARM64") == 0) { ++ arch_mask |= ARCH_ARM64; ++ } else if (strcmp(val, "RISCV64") == 0) { ++ arch_mask |= ARCH_RISCV64; ++ } else { ++ PRINT_FAIL("bad arch spec: '%s'", val); ++ err = -EINVAL; ++ goto cleanup; ++ } + } else if (str_has_pfx(s, TEST_BTF_PATH)) { + spec->btf_custom_path = s + sizeof(TEST_BTF_PATH) - 1; + } + } + ++ spec->arch_mask = arch_mask; ++ + if (spec->mode_mask == 0) + spec->mode_mask = PRIV; + +@@ -336,17 +457,25 @@ static int parse_test_spec(struct test_loader *tester, + spec->unpriv.execute = spec->priv.execute; + } + +- if (!spec->unpriv.expect_msgs) { +- size_t sz = spec->priv.expect_msg_cnt * sizeof(void *); ++ if (spec->unpriv.expect_msgs.cnt == 0) { ++ for (i = 0; i < spec->priv.expect_msgs.cnt; i++) { ++ struct expect_msg *msg = &spec->priv.expect_msgs.patterns[i]; + +- spec->unpriv.expect_msgs = malloc(sz); +- if (!spec->unpriv.expect_msgs) { +- PRINT_FAIL("failed to allocate memory for unpriv.expect_msgs\n"); +- err = -ENOMEM; +- goto cleanup; ++ err = push_msg(msg->substr, msg->regex_str, ++ &spec->unpriv.expect_msgs); ++ if (err) ++ goto cleanup; ++ } ++ } ++ if (spec->unpriv.expect_xlated.cnt == 0) { ++ for (i = 0; i < spec->priv.expect_xlated.cnt; i++) { ++ struct expect_msg *msg = &spec->priv.expect_xlated.patterns[i]; ++ ++ err = push_msg(msg->substr, msg->regex_str, ++ &spec->unpriv.expect_xlated); ++ if (err) ++ goto cleanup; + } +- memcpy(spec->unpriv.expect_msgs, spec->priv.expect_msgs, sz); +- spec->unpriv.expect_msg_cnt = spec->priv.expect_msg_cnt; + } + } + +@@ -386,7 +515,6 @@ static void prepare_case(struct test_loader *tester, + bpf_program__set_flags(prog, prog_flags | spec->prog_flags); + + tester->log_buf[0] = '\0'; +- tester->next_match_pos = 0; + } + + static void emit_verifier_log(const char *log_buf, bool force) +@@ -396,33 +524,48 @@ static void emit_verifier_log(const char *log_buf, bool force) + fprintf(stdout, "VERIFIER LOG:\n=============\n%s=============\n", log_buf); + } + +-static void validate_case(struct test_loader *tester, +- struct test_subspec *subspec, +- struct bpf_object *obj, +- struct bpf_program *prog, +- int load_err) ++static void emit_xlated(const char *xlated, bool force) + { +- int i, j; +- +- for (i = 0; i < subspec->expect_msg_cnt; i++) { +- char *match; +- const char *expect_msg; ++ if (!force && env.verbosity == VERBOSE_NONE) ++ return; ++ fprintf(stdout, "XLATED:\n=============\n%s=============\n", xlated); ++} + +- expect_msg = subspec->expect_msgs[i]; ++static void validate_msgs(char *log_buf, struct expected_msgs *msgs, ++ void (*emit_fn)(const char *buf, bool force)) ++{ ++ regmatch_t reg_match[1]; ++ const char *log = log_buf; ++ int i, j, err; ++ ++ for (i = 0; i < msgs->cnt; i++) { ++ struct expect_msg *msg = &msgs->patterns[i]; ++ const char *match = NULL; ++ ++ if (msg->substr) { ++ match = strstr(log, msg->substr); ++ if (match) ++ log = match + strlen(msg->substr); ++ } else { ++ err = regexec(&msg->regex, log, 1, reg_match, 0); ++ if (err == 0) { ++ match = log + reg_match[0].rm_so; ++ log += reg_match[0].rm_eo; ++ } ++ } + +- match = strstr(tester->log_buf + tester->next_match_pos, expect_msg); + if (!ASSERT_OK_PTR(match, "expect_msg")) { +- /* if we are in verbose mode, we've already emitted log */ + if (env.verbosity == VERBOSE_NONE) +- emit_verifier_log(tester->log_buf, true /*force*/); +- for (j = 0; j < i; j++) +- fprintf(stderr, +- "MATCHED MSG: '%s'\n", subspec->expect_msgs[j]); +- fprintf(stderr, "EXPECTED MSG: '%s'\n", expect_msg); ++ emit_fn(log_buf, true /*force*/); ++ for (j = 0; j <= i; j++) { ++ msg = &msgs->patterns[j]; ++ fprintf(stderr, "%s %s: '%s'\n", ++ j < i ? "MATCHED " : "EXPECTED", ++ msg->substr ? "SUBSTR" : " REGEX", ++ msg->substr ?: msg->regex_str); ++ } + return; + } +- +- tester->next_match_pos = match - tester->log_buf + strlen(expect_msg); + } + } + +@@ -550,6 +693,51 @@ static bool should_do_test_run(struct test_spec *spec, struct test_subspec *subs + return true; + } + ++/* Get a disassembly of BPF program after verifier applies all rewrites */ ++static int get_xlated_program_text(int prog_fd, char *text, size_t text_sz) ++{ ++ struct bpf_insn *insn_start = NULL, *insn, *insn_end; ++ __u32 insns_cnt = 0, i; ++ char buf[64]; ++ FILE *out = NULL; ++ int err; ++ ++ err = get_xlated_program(prog_fd, &insn_start, &insns_cnt); ++ if (!ASSERT_OK(err, "get_xlated_program")) ++ goto out; ++ out = fmemopen(text, text_sz, "w"); ++ if (!ASSERT_OK_PTR(out, "open_memstream")) ++ goto out; ++ insn_end = insn_start + insns_cnt; ++ insn = insn_start; ++ while (insn < insn_end) { ++ i = insn - insn_start; ++ insn = disasm_insn(insn, buf, sizeof(buf)); ++ fprintf(out, "%d: %s\n", i, buf); ++ } ++ fflush(out); ++ ++out: ++ free(insn_start); ++ if (out) ++ fclose(out); ++ return err; ++} ++ ++static bool run_on_current_arch(int arch_mask) ++{ ++ if (arch_mask == 0) ++ return true; ++#if defined(__x86_64__) ++ return arch_mask & ARCH_X86_64; ++#elif defined(__aarch64__) ++ return arch_mask & ARCH_ARM64; ++#elif defined(__riscv) && __riscv_xlen == 64 ++ return arch_mask & ARCH_RISCV64; ++#endif ++ return false; ++} ++ + /* this function is forced noinline and has short generic name to look better + * in test_progs output (in case of a failure) + */ +@@ -574,6 +762,11 @@ void run_subtest(struct test_loader *tester, + if (!test__start_subtest(subspec->name)) + return; + ++ if (!run_on_current_arch(spec->arch_mask)) { ++ test__skip(); ++ return; ++ } ++ + if (unpriv) { + if (!can_execute_unpriv(tester, spec)) { + test__skip(); +@@ -634,9 +827,17 @@ void run_subtest(struct test_loader *tester, + goto tobj_cleanup; + } + } +- + emit_verifier_log(tester->log_buf, false /*force*/); +- validate_case(tester, subspec, tobj, tprog, err); ++ validate_msgs(tester->log_buf, &subspec->expect_msgs, emit_verifier_log); ++ ++ if (subspec->expect_xlated.cnt) { ++ err = get_xlated_program_text(bpf_program__fd(tprog), ++ tester->log_buf, tester->log_buf_sz); ++ if (err) ++ goto tobj_cleanup; ++ emit_xlated(tester->log_buf, false /*force*/); ++ validate_msgs(tester->log_buf, &subspec->expect_xlated, emit_xlated); ++ } + + if (should_do_test_run(spec, subspec)) { + /* For some reason test_verifier executes programs +diff --git a/tools/testing/selftests/bpf/test_lru_map.c b/tools/testing/selftests/bpf/test_lru_map.c +index 4d0650cfb5cd8b..fda7589c50236c 100644 +--- a/tools/testing/selftests/bpf/test_lru_map.c ++++ b/tools/testing/selftests/bpf/test_lru_map.c +@@ -126,7 +126,8 @@ static int sched_next_online(int pid, int *next_to_try) + + while (next < nr_cpus) { + CPU_ZERO(&cpuset); +- CPU_SET(next++, &cpuset); ++ CPU_SET(next, &cpuset); ++ next++; + if (!sched_setaffinity(pid, sizeof(cpuset), &cpuset)) { + ret = 0; + break; +diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c +index 89ff704e9dad5e..d5d0cb4eb1975b 100644 +--- a/tools/testing/selftests/bpf/test_progs.c ++++ b/tools/testing/selftests/bpf/test_progs.c +@@ -10,7 +10,6 @@ + #include <sched.h> + #include <signal.h> + #include <string.h> +-#include <execinfo.h> /* backtrace */ + #include <sys/sysinfo.h> /* get_nprocs */ + #include <netinet/in.h> + #include <sys/select.h> +@@ -19,6 +18,21 @@ + #include <bpf/btf.h> + #include "json_writer.h" + ++#ifdef __GLIBC__ ++#include <execinfo.h> /* backtrace */ ++#endif ++ ++/* Default backtrace funcs if missing at link */ ++__weak int backtrace(void **buffer, int size) ++{ ++ return 0; ++} ++ ++__weak void backtrace_symbols_fd(void *const *buffer, int size, int fd) ++{ ++ dprintf(fd, "<backtrace not supported>\n"); ++} ++ + static bool verbose(void) + { + return env.verbosity > VERBOSE_NONE; +@@ -1731,7 +1745,7 @@ int main(int argc, char **argv) + /* launch workers if requested */ + env.worker_id = -1; /* main process */ + if (env.workers) { +- env.worker_pids = calloc(sizeof(__pid_t), env.workers); ++ env.worker_pids = calloc(sizeof(pid_t), env.workers); + env.worker_socks = calloc(sizeof(int), env.workers); + if (env.debug) + fprintf(stdout, "Launching %d workers.\n", env.workers); +diff --git a/tools/testing/selftests/bpf/test_progs.h b/tools/testing/selftests/bpf/test_progs.h +index 0ba5a20b19ba8e..8e997de596db05 100644 +--- a/tools/testing/selftests/bpf/test_progs.h ++++ b/tools/testing/selftests/bpf/test_progs.h +@@ -438,7 +438,6 @@ typedef int (*pre_execution_cb)(struct bpf_object *obj); + struct test_loader { + char *log_buf; + size_t log_buf_sz; +- size_t next_match_pos; + pre_execution_cb pre_execution_cb; + + struct bpf_object *obj; +diff --git a/tools/testing/selftests/bpf/testing_helpers.c b/tools/testing/selftests/bpf/testing_helpers.c +index d5379a0e6da804..680e452583a78b 100644 +--- a/tools/testing/selftests/bpf/testing_helpers.c ++++ b/tools/testing/selftests/bpf/testing_helpers.c +@@ -220,13 +220,13 @@ int parse_test_list(const char *s, + bool is_glob_pattern) + { + char *input, *state = NULL, *test_spec; +- int err = 0; ++ int err = 0, cnt = 0; + + input = strdup(s); + if (!input) + return -ENOMEM; + +- while ((test_spec = strtok_r(state ? NULL : input, ",", &state))) { ++ while ((test_spec = strtok_r(cnt++ ? NULL : input, ",", &state))) { + err = insert_test(set, test_spec, is_glob_pattern); + if (err) + break; +@@ -451,7 +451,7 @@ int get_xlated_program(int fd_prog, struct bpf_insn **buf, __u32 *cnt) + + *cnt = xlated_prog_len / buf_element_size; + *buf = calloc(*cnt, buf_element_size); +- if (!buf) { ++ if (!*buf) { + perror("can't allocate xlated program buffer"); + return -ENOMEM; + } +diff --git a/tools/testing/selftests/bpf/unpriv_helpers.c b/tools/testing/selftests/bpf/unpriv_helpers.c +index b6d016461fb023..220f6a96381345 100644 +--- a/tools/testing/selftests/bpf/unpriv_helpers.c ++++ b/tools/testing/selftests/bpf/unpriv_helpers.c +@@ -2,7 +2,6 @@ + + #include <stdbool.h> + #include <stdlib.h> +-#include <error.h> + #include <stdio.h> + #include <string.h> + #include <unistd.h> +diff --git a/tools/testing/selftests/bpf/veristat.c b/tools/testing/selftests/bpf/veristat.c +index b2854238d4a0eb..fd9780082ff48a 100644 +--- a/tools/testing/selftests/bpf/veristat.c ++++ b/tools/testing/selftests/bpf/veristat.c +@@ -784,13 +784,13 @@ static int parse_stat(const char *stat_name, struct stat_specs *specs) + static int parse_stats(const char *stats_str, struct stat_specs *specs) + { + char *input, *state = NULL, *next; +- int err; ++ int err, cnt = 0; + + input = strdup(stats_str); + if (!input) + return -ENOMEM; + +- while ((next = strtok_r(state ? NULL : input, ",", &state))) { ++ while ((next = strtok_r(cnt++ ? NULL : input, ",", &state))) { + err = parse_stat(next, specs); + if (err) { + free(input); +@@ -1493,7 +1493,7 @@ static int parse_stats_csv(const char *filename, struct stat_specs *specs, + while (fgets(line, sizeof(line), f)) { + char *input = line, *state = NULL, *next; + struct verif_stats *st = NULL; +- int col = 0; ++ int col = 0, cnt = 0; + + if (!header) { + void *tmp; +@@ -1511,7 +1511,7 @@ static int parse_stats_csv(const char *filename, struct stat_specs *specs, + *stat_cntp += 1; + } + +- while ((next = strtok_r(state ? NULL : input, ",\n", &state))) { ++ while ((next = strtok_r(cnt++ ? NULL : input, ",\n", &state))) { + if (header) { + /* for the first line, set up spec stats */ + err = parse_stat(next, specs); +diff --git a/tools/testing/selftests/dt/test_unprobed_devices.sh b/tools/testing/selftests/dt/test_unprobed_devices.sh +index 2d7e70c5ad2d36..5e3f42ef249eec 100755 +--- a/tools/testing/selftests/dt/test_unprobed_devices.sh ++++ b/tools/testing/selftests/dt/test_unprobed_devices.sh +@@ -34,8 +34,21 @@ nodes_compatible=$( + # Check if node is available + if [[ -e "${node}"/status ]]; then + status=$(tr -d '\000' < "${node}"/status) +- [[ "${status}" != "okay" && "${status}" != "ok" ]] && continue ++ if [[ "${status}" != "okay" && "${status}" != "ok" ]]; then ++ if [ -n "${disabled_nodes_regex}" ]; then ++ disabled_nodes_regex="${disabled_nodes_regex}|${node}" ++ else ++ disabled_nodes_regex="${node}" ++ fi ++ continue ++ fi + fi ++ ++ # Ignore this node if one of its ancestors was disabled ++ if [ -n "${disabled_nodes_regex}" ]; then ++ echo "${node}" | grep -q -E "${disabled_nodes_regex}" && continue ++ fi ++ + echo "${node}" | sed -e 's|\/proc\/device-tree||' + done | sort + ) +diff --git a/tools/testing/selftests/ftrace/test.d/00basic/test_ownership.tc b/tools/testing/selftests/ftrace/test.d/00basic/test_ownership.tc +index c45094d1e1d2db..803efd7b56c77d 100644 +--- a/tools/testing/selftests/ftrace/test.d/00basic/test_ownership.tc ++++ b/tools/testing/selftests/ftrace/test.d/00basic/test_ownership.tc +@@ -6,6 +6,18 @@ original_group=`stat -c "%g" .` + original_owner=`stat -c "%u" .` + + mount_point=`stat -c '%m' .` ++ ++# If stat -c '%m' does not work (e.g. busybox) or failed, try to use the ++# current working directory (which should be a tracefs) as the mount point. ++if [ ! -d "$mount_point" ]; then ++ if mount | grep -qw $PWD ; then ++ mount_point=$PWD ++ else ++ # If PWD doesn't work, that is an environmental problem. ++ exit_unresolved ++ fi ++fi ++ + mount_options=`mount | grep "$mount_point" | sed -e 's/.*(\(.*\)).*/\1/'` + + # find another owner and group that is not the original +diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func_set_ftrace_file.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func_set_ftrace_file.tc +index 073a748b9380a1..263f6b798c853e 100644 +--- a/tools/testing/selftests/ftrace/test.d/ftrace/func_set_ftrace_file.tc ++++ b/tools/testing/selftests/ftrace/test.d/ftrace/func_set_ftrace_file.tc +@@ -19,7 +19,14 @@ fail() { # mesg + + FILTER=set_ftrace_filter + FUNC1="schedule" +-FUNC2="sched_tick" ++if grep '^sched_tick\b' available_filter_functions; then ++ FUNC2="sched_tick" ++elif grep '^scheduler_tick\b' available_filter_functions; then ++ FUNC2="scheduler_tick" ++else ++ exit_unresolved ++fi ++ + + ALL_FUNCS="#### all functions enabled ####" + +diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_char.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_char.tc +index e21c9c27ece476..77f4c07cdcb899 100644 +--- a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_char.tc ++++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_char.tc +@@ -1,7 +1,7 @@ + #!/bin/sh + # SPDX-License-Identifier: GPL-2.0 + # description: Kprobe event char type argument +-# requires: kprobe_events ++# requires: kprobe_events available_filter_functions + + case `uname -m` in + x86_64) +diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc +index 93217d4595563f..39001073f7ed5d 100644 +--- a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc ++++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc +@@ -1,7 +1,7 @@ + #!/bin/sh + # SPDX-License-Identifier: GPL-2.0 + # description: Kprobe event string type argument +-# requires: kprobe_events ++# requires: kprobe_events available_filter_functions + + case `uname -m` in + x86_64) +diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h +index 76c2a6945d3e83..f9214e7cdd1345 100644 +--- a/tools/testing/selftests/kselftest.h ++++ b/tools/testing/selftests/kselftest.h +@@ -61,6 +61,7 @@ + #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + #endif + ++#if defined(__i386__) || defined(__x86_64__) /* arch */ + /* + * gcc cpuid.h provides __cpuid_count() since v4.4. + * Clang/LLVM cpuid.h provides __cpuid_count() since v3.4.0. +@@ -75,6 +76,7 @@ + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ + : "0" (level), "2" (count)) + #endif ++#endif /* end arch */ + + /* define kselftest exit codes */ + #define KSFT_PASS 0 +diff --git a/tools/testing/selftests/net/netfilter/ipvs.sh b/tools/testing/selftests/net/netfilter/ipvs.sh +index 4ceee9fb39495b..d3edb16cd4b3f6 100755 +--- a/tools/testing/selftests/net/netfilter/ipvs.sh ++++ b/tools/testing/selftests/net/netfilter/ipvs.sh +@@ -97,7 +97,7 @@ cleanup() { + } + + server_listen() { +- ip netns exec "$ns2" socat -u -4 TCP-LISTEN:8080,reuseaddr STDOUT > "${outfile}" & ++ ip netns exec "$ns2" timeout 5 socat -u -4 TCP-LISTEN:8080,reuseaddr STDOUT > "${outfile}" & + server_pid=$! + sleep 0.2 + } +diff --git a/tools/testing/selftests/resctrl/cat_test.c b/tools/testing/selftests/resctrl/cat_test.c +index 55315ed695f47e..18565f02163e72 100644 +--- a/tools/testing/selftests/resctrl/cat_test.c ++++ b/tools/testing/selftests/resctrl/cat_test.c +@@ -293,12 +293,12 @@ static int cat_run_test(const struct resctrl_test *test, const struct user_param + + static bool arch_supports_noncont_cat(const struct resctrl_test *test) + { +- unsigned int eax, ebx, ecx, edx; +- + /* AMD always supports non-contiguous CBM. */ + if (get_vendor() == ARCH_AMD) + return true; + ++#if defined(__i386__) || defined(__x86_64__) /* arch */ ++ unsigned int eax, ebx, ecx, edx; + /* Intel support for non-contiguous CBM needs to be discovered. */ + if (!strcmp(test->resource, "L3")) + __cpuid_count(0x10, 1, eax, ebx, ecx, edx); +@@ -308,6 +308,9 @@ static bool arch_supports_noncont_cat(const struct resctrl_test *test) + return false; + + return ((ecx >> 3) & 1); ++#endif /* end arch */ ++ ++ return false; + } + + static int noncont_cat_run_test(const struct resctrl_test *test, +diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c +index 1192942aef911d..3163bcf8148a64 100644 +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -5500,6 +5500,7 @@ __visible bool kvm_rebooting; + EXPORT_SYMBOL_GPL(kvm_rebooting); + + static DEFINE_PER_CPU(bool, hardware_enabled); ++static DEFINE_MUTEX(kvm_usage_lock); + static int kvm_usage_count; + + static int __hardware_enable_nolock(void) +@@ -5532,10 +5533,10 @@ static int kvm_online_cpu(unsigned int cpu) + * be enabled. Otherwise running VMs would encounter unrecoverable + * errors when scheduled to this CPU. + */ +- mutex_lock(&kvm_lock); ++ mutex_lock(&kvm_usage_lock); + if (kvm_usage_count) + ret = __hardware_enable_nolock(); +- mutex_unlock(&kvm_lock); ++ mutex_unlock(&kvm_usage_lock); + return ret; + } + +@@ -5555,10 +5556,10 @@ static void hardware_disable_nolock(void *junk) + + static int kvm_offline_cpu(unsigned int cpu) + { +- mutex_lock(&kvm_lock); ++ mutex_lock(&kvm_usage_lock); + if (kvm_usage_count) + hardware_disable_nolock(NULL); +- mutex_unlock(&kvm_lock); ++ mutex_unlock(&kvm_usage_lock); + return 0; + } + +@@ -5574,9 +5575,9 @@ static void hardware_disable_all_nolock(void) + static void hardware_disable_all(void) + { + cpus_read_lock(); +- mutex_lock(&kvm_lock); ++ mutex_lock(&kvm_usage_lock); + hardware_disable_all_nolock(); +- mutex_unlock(&kvm_lock); ++ mutex_unlock(&kvm_usage_lock); + cpus_read_unlock(); + } + +@@ -5607,7 +5608,7 @@ static int hardware_enable_all(void) + * enable hardware multiple times. + */ + cpus_read_lock(); +- mutex_lock(&kvm_lock); ++ mutex_lock(&kvm_usage_lock); + + r = 0; + +@@ -5621,7 +5622,7 @@ static int hardware_enable_all(void) + } + } + +- mutex_unlock(&kvm_lock); ++ mutex_unlock(&kvm_usage_lock); + cpus_read_unlock(); + + return r; +@@ -5649,13 +5650,13 @@ static int kvm_suspend(void) + { + /* + * Secondary CPUs and CPU hotplug are disabled across the suspend/resume +- * callbacks, i.e. no need to acquire kvm_lock to ensure the usage count +- * is stable. Assert that kvm_lock is not held to ensure the system +- * isn't suspended while KVM is enabling hardware. Hardware enabling +- * can be preempted, but the task cannot be frozen until it has dropped +- * all locks (userspace tasks are frozen via a fake signal). ++ * callbacks, i.e. no need to acquire kvm_usage_lock to ensure the usage ++ * count is stable. Assert that kvm_usage_lock is not held to ensure ++ * the system isn't suspended while KVM is enabling hardware. Hardware ++ * enabling can be preempted, but the task cannot be frozen until it has ++ * dropped all locks (userspace tasks are frozen via a fake signal). + */ +- lockdep_assert_not_held(&kvm_lock); ++ lockdep_assert_not_held(&kvm_usage_lock); + lockdep_assert_irqs_disabled(); + + if (kvm_usage_count) +@@ -5665,7 +5666,7 @@ static int kvm_suspend(void) + + static void kvm_resume(void) + { +- lockdep_assert_not_held(&kvm_lock); ++ lockdep_assert_not_held(&kvm_usage_lock); + lockdep_assert_irqs_disabled(); + + if (kvm_usage_count) |